题目: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;
}
};