33.Search in Rotated Sorted Array
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.
Subscribe to see which companies asked this question
题解:
二分查找针对的是有序数组,此题对所给的数组做了一些变化,给出了一个经过循环位移后有序的数组,让你在这个基础上进行查找。
假设我们已经知道了位移量k,那么其实我们可以通过位移的手段,等效的形成一个有序数组。例如,假如你想取出有序数组中的下标为i的值,可以使用nums[(i+k)%n]来获取,其中n为数组长度。既然如此,我们就可以使用二分了。
现在我们的问题就是如何快速求出位移量k了,好在k也可以二分的求出来。假设我们要在[lo,hi)的区间中寻找偏移量k,如果nums[mi] >= nums[0],说明[0,mi]是有序的,从最高点滑向最低点的坡(亦即k)在[mi+1,hi)中,反之则说明在[lo,mi]中,以此为基础我们可以二分出k。
算法的时间复杂度为O(logn)。
代码:
class Solution {
public:
int search(vector<int>& nums, int target) {
set_offset(nums);
printf("off = %d\n", offset);
int lo = 0, hi = nums.size();
while (lo < hi) {
int mi = (lo+hi) / 2;
int pivot = at(nums, mi);
if (target == pivot) return (mi+offset)%nums.size();
if (target > pivot) lo = mi+1;
else hi = mi;
}
return -1;
}
void set_offset(vector<int> &nums) {
int n = nums.size();
int lo = 0, hi = n;
while (lo < hi) {
int mi = (lo+hi) / 2;
if (nums[0] <= nums[mi]) lo = mi+1;
else hi = mi;
}
offset = lo;
}
int& at(vector<int>& nums, int idx) {
return nums[(idx+offset)%nums.size()];
}
int offset;
};