题目:33. Search in Rotated Sorted Array
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.
题目解释:假设一个有序数组被旋转,你有一个目标数去在这个数组中查找它的位置,找不到返回-1.
附加条件:假设这个有序数组没有重复元素。
(LeetCode的题目网上大家分享的题解有非常多,我也就是将解答代码记录下来以供自己更为理解。)
1、首先我们理解题目条件:①有序数组 ②以某点为原点旋转
有序数组我们一般第一反应是二分法查找,而旋转的数组的特点还是局部有序。只是以原始数组第一位置为分割点左右子数组分别有序。如下的数组中:
4 | 5 | 6 | 7 | 0 | 1 | 2 |
首先,得到当前数组的中间点mid,
1、如果该点值arr[mid]=target,那就最好不过了,直接返回该点的索引;
2、否则找到左右两边哪个是局部有序的,进行排除法查找,①若左边有序子数组,则arr[start]<=arr[mid],那么久判断target是否居于arr[start]和arr[mid]值之间,如果是,则整个查找数组缩小为左边数组范围,即将end=mid,接下来的查找范围为[start,mid]规模缩小一半的数组。②左边若不是有序,那么右边必然有序,则查找target是否在右边,即判断target是否在arr[mid]和arr[end]值之间,如果是那么target就在右边子数组,将start=mid+1(为什么start是mid+1后移一位,而end直接等于mid而不用-1迁移一位呢?这是因为我们计算mid的时候是将(start+end)/2的结果转为int时候截断了可能有的0.5因此mid是靠近start的,因此将mid作为结尾end的时候是不需要前移mid-1的,这个也是我当初比较疑惑的一点,这些边界条件我们必须揪想清楚)。
如果最终也没有碰到arr[mid]==target,那就是整个数组都找不到target,因此返回-1即可。
这样的方法的优点是不用判断数组的情况
arr.size()==0;则start=0;end=-1;则直接不进入循环,直接返回-1;
arr.size()==1;则start=0;end=0;计算出来的mid=0;因此判断arr[mid],也就是唯一的这个元素是否为target,不是的话下面的if条件判断将会start=mid+1,此时start>end,也不能进入下轮循环,退出return -1;
arr.size()>=2,情况就以此类推
代码如下:
class Solution { public: int search(vector<int>& arr, int target) { int start = 0,end = arr.size()-1; while (start<=end) { int mid = start + (end - start) / 2; if (target == arr[mid]) return mid; if(arr[start]<=arr[mid]) { if (arr[start] <= target&&target < arr[mid]) end = mid; else start = mid + 1; } else { if (arr[mid] < target&&target <= arr[end]) start = mid + 1; else end = mid; } } return -1; } };