Title:
Suppose an array sorted in ascending order 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.
这道题就是给一个升序的数组,然后会以某一点做一个调换,也就是整体的顺序不会是升序。而是有升有降。然后在其中找到我要的target,如果有返回序号,么有返回-1.
第一思路就是遍历,但这种思路太过简单和耗时,直接pass。
第二思路就是二分法查找,对于这种有一定规律的。
那么具体分析这个调换会产生什么样的数组:无论如何调换,数组中间那个数,左边或者是右边,总有一边是升序。比如2456701. 6的左边是升序。其实很好理解。
那么剩下的问题就是找到到底是哪边是升序。很好找:
0 1 2 4 5 6 7
7 0 1 2 4 5 6
6 7 0 1 2 4 5
5 6 7 0 1 2 4
4 5 6 7 0 1 2
2 4 5 6 7 0 1
1 2 4 5 6 7 0
如果中间的数大于右边的数,那么右边肯定有降序,那么根据上面的分析,肯定有一边是升序,那么左边是升序。
如果中间的数小于右边的数,那么这里有两种情况,如果最右边的数是最大的,那么右边肯定是升序,左边也是升序,整个就是升序。如果最右边的数不是最大,那么最大肯定在左边,那么左边肯定就有减序,那么右边一定是升序。
知道这个规律就很好写二分法了:
Solution:
int search(int* nums, int numsSize, int target) {
int mid, left,right;
int i;
if (numsSize==0)
return -1;
if (numsSize==1) {
if (target==nums[0])
return 0;
else
return -1;
}
left=0;
right=numsSize-1;
while ( left <= right) {
mid=(left+right)/2;
if (nums[mid]==target)
return mid;
else if (nums[mid]<nums[right]) {
if (target>nums[mid] && target<=nums[right])
left=mid+1;
else
right=mid-1;
}
else {
if (target>=nums[left] && target<nums[mid]) {
right=mid-1;
}
else
left=mid+1;
}
}
return -1;
}