leetcode:Search in Rotated Sorted Array II
贴一下题目:
1.Suppose a sorted array is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7
might become 4 5 6 7 0 1 2
).
You are given a target value to search. If found in the array return its index, otherwise return -1.
You may assume no duplicate exists in the array.
------------------------------------------------------------------------------------------------------
2.Follow up for "Search in Rotated Sorted Array":
What if duplicates are allowed?
Would this affect the run-time complexity? How and why?
Write a function to determine if a given target is in the array.
------------------------------------------------------------------------------------------------------
这道题目与上面那一道有所不同,其允许重复,我在纸上写了几个这样的允许重复的例子,按照这个例子去修改前题的代码,结果依旧是错的,其实自己造例子不是一件坏事,但不好的地方在于你想的用于测试的例子永远都是那么几种,无法考虑周全,这时依据例子盲目的改代码就很傻了,结果可能是漏洞百出,我感觉应该是要以思路为主导,在上题的正确思路的基础上进行修改,比较上下两题的细微差异所带来的问题,修改思路,然后才是改代码。
上题不允许重复,代码如下:
1 class Solution { 2 public: 3 int search(int A[], int n, int target) { 4 int first=0,last=n-1,mid=0; 5 while(first<=last){ 6 mid=(first+last)/2; 7 if(A[mid]==target) return mid; 8 9 if(A[first]<=A[mid]) 10 {if(A[first]<=target&&A[mid]>target) last=mid-1; 11 else first=mid+1;} 12 else{if(A[mid]<target&&A[last]>=target) first=mid+1; 13 else last=mid-1; } 14 15 } return -1; 16 } 17 };
if(A[first]<=A[mid])这一句就可以将有序的部分判别出来,如果前面满足,自然是前面有序,如果前面不满足,那就肯定是后面有序了,整个程序有两个入口,if和else二者只入其一,while内部做的都是修改左右边界,把mid计算放在开始的地方是很好的,一次循环只更新一次mid。
允许重复时就不可以通过一句if(A[first]<=A[mid])来判断出有序和无序了,当然这时肯定也会分成有序和无序两部分,因为等号时存在无序的情况(11311111111111111)
所以思路要有所改变,大方向依然是上面的思路,但此时要将有序判断部分修改,至少要将这两种情况拆分开来,if(A[first]<A[mid])肯定是有序的,这时前面有序,如果满足这一条那就判断在不在前半段,在就last=mid-1,不在的话那肯定就在(无序)的后半段了,这时只要将first=mid+1就好了,还有一种情况是后半段有序前半段无序,这时该怎么处理呢,有顺序的后半段该怎么判别出来呢,因为有序对应的是两种情况,而我们希望通过一个判断就区分开来,解决办法是这时不是判断后半段有序来区分,而是判断前半段无序来区分if(A[first]>A[mid])说明前半段无序,那言外之意是后半段有序了,如果满足此条件我们就判断target会不会在后半段,如果在后半段那没的说first=mid+1,如果不在后半段那肯定在前半段,那我们就last=mid-1,这样还是将范围缩小了。
但是,对于相等的情况该怎么办呢,(11311111111111111),我们就逐步排除元素直至出现有序,方法是如果上面两条都不满足就在最后first++,因为上面都不满足肯定是
A[first]==A[mid]了,所以也就是说first不是target了,这样一次循环,运气好砍掉一半,运气差就排出一个元素,最后总是会找到的。
我这个大菜鸟在编程时出现的问题是对if语句理解不好,两个判断分支的话两个入口必进其一,但三个时就不会处理了(此时处理的次序也很重要),三个最多只进其一。
1 if(表达式一) 2 if(表达式二) 语句一; 3 else 语句二; 4 else 5 语句三。 6 //if else,二者必进其一,里面可以嵌套处理,但要注意搭配。 7 //======================================================= 8 if(表达式1) 语句1; 9 else if(表达式2) 语句2; 10 else if(表达式3) 语句3; 11 else if(表达式4) 语句4; 12 、、、、、、、、、、、、 13 else 语句n; 14 //此时是多必进其一,多只可进其一。 15 //======================================================= 16 if(表达式1) 语句1; 17 if(表达式2) 语句2; 18 if(表达式3) 语句3; 19 if(表达式4) 语句4; 20 if(表达式5) 语句5; 21 、、、、、、、、、、、、 22 else 语句n; 23 24 //这时顺序判断进入,前面if语句内部的处理可能会影响到后面的判断要注意,最后的else也可以去掉。
最后是题目解答:
1 class Solution { 2 public: 3 bool search(int A[], int n, int target) { 4 int first=0,last=n-1,mid=0; 5 while(first<=last){ 6 mid=(first+last)/2; 7 if(A[mid]==target) return true; 8 9 if(A[first]<A[mid]) 10 {if(A[first]<=target&&A[mid]>target) last=mid-1; 11 else first=mid+1;} 12 else if(A[first]>A[mid]) 13 { 14 if(A[mid]<target&&A[last]>=target){first=mid+1;} 15 else last=mid-1; } 16 else first++; 17 18 } return false; 19 20 } 21 };