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. 思路
先找到最小值的下标,然后根据比较结果判断是哪一段有序数组里进行二分查找。
最小值的查找通过递归进行。对于某一段循环有序数组,二分为两段进行定位查找,前段的尾节点等于后段的首节点,即有一个交叉点,避免漏掉。如果两段都是有序的,说明整体是有序的,返回前段的首节点。如果某一段的首大于尾,则在这一段里面进行递归查找。
3. 代码
class Solution {
public:
// 先找到最小点,然后在在其中一边做二分查找。
// 如果是有序的, 则末端大于首端; 基于此可以二分定位到最小点
int search(vector<int>& nums, int target) {
int sz = nums.size();
if (sz == 0) return -1;
if (sz == 1) return nums[0] == target ? 0 : -1;
int min_idx = find_min_idx(nums, 0, nums.size());
//cout << min_idx << " " << nums[min_idx] << endl;
if (target <= nums[sz-1]) {
return bsearch(nums, min_idx, sz, target);
} else {
return bsearch(nums, 0, min_idx, target);
}
}
int find_min_idx(vector<int>& nums, int i, int j) {
if (i >= j) return -1;
if (j - i == 1) return i;
if (j - i == 2) return nums[i] > nums[j-1] ? j-1 : i;
int k = (i + j) / 2;
if (nums[k] < nums[i]) {
return find_min_idx(nums, i, k+1);
} else if (nums[k] > nums[j-1]) {
return find_min_idx(nums, k, j);
} else {
return i;
}
}
int bsearch(vector<int>& nums, int i, int j , int target) {
if (j <= i) return -1;
int k = (i + j) / 2;
if (nums[k] == target) {
return k;
} else if (nums[k] > target) {
return bsearch(nums, i, k, target);
} else {
return bsearch(nums, k+1, j, target);
}
}
};