https://leetcode.com/problems/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 become4 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.
solution 1
如果是一个未经旋转的有序数组,显然可以直接用二分查找来做。经过旋转的数组,其实本质就是两个排序数组,我们可以分别在两个数组中进行二分查找,难点是找到两个数组的分界线,用遍历的方式来寻找分界线复杂度为o(n),显然不是我们期待的solution,其实只要意识到整个数组最左边与最右边两个值的特殊性,我们同样可以使用二分的方式来寻找分界线。代码如下:
class Solution {
public:
int search(vector<int>& nums, int target) {
if (nums.empty()) {
return -1;
}
/* without rotating, excute binary search directly */
int left = 0, right = nums.size() - 1;
if (nums[left] <= nums[right]) {
return binarySearch(nums, left, right, target);
}
/* include two elements at least */
left = determineBoundary(nums);
right = left + 1;
if (nums[0] <= target && target <= nums[left]) {
return binarySearch(nums, 0, left, target);
} else if (nums[right] <= target && target <= nums[nums.size() - 1]) {
return binarySearch(nums, right, nums.size() - 1, target);
} else {
return -1;
}
}
private:
int binarySearch(const vector<int> &nums, const int start, const int end, int target) {
int left = start, right = end, middle;
while (left + 1 < right) {
middle = (left + right) >> 1;
if (target == nums[middle]) {
return middle;
} else if (target > nums[middle]) {
left = middle;
} else if (target < nums[middle]) {
right = middle;
}
}
if (target == nums[left]) {
return left;
}
if (target == nums[right]) {
return right;
}
return -1;
}
int determineBoundary(const vector<int> &nums) {
int leftValue = nums[0], rightValue = nums[nums.size() - 1];
int left = 0, right = nums.size() - 1, middle;
while (left + 1 < right) {
middle = (left + right) >> 1;
if (leftValue < nums[middle]) {
left = middle;
}
if (nums[middle] < rightValue) {
right = middle;
}
}
return left;
}
};
solution 2
以上的方案我们通过寻找两个排序数组的分界线,从而对其分别使用二分查找来完成搜索。实际上,该题不必如此繁琐,我们可以省去寻找分界线的步骤,直接进行二分查找。代码如下:
// author: Jian-xin Zhou
class Solution {
public:
int search(vector<int>& nums, int target) {
if (nums.empty()) {
return -1;
}
int left = 0, right = nums.size() - 1, middle;
while (left + 1 < right) {
middle = (left + right) >> 1;
if (target == nums[middle]) {
return middle;
}
if (nums[left] < nums[middle]) {
if (nums[left] <= target && target < nums[middle]) {
right = middle;
} else {
left = middle;
}
}
if (nums[middle] < nums[right]) {
if (nums[middle] < target && target <= nums[right]) {
left = middle;
} else {
right = middle;
}
}
}
if (target == nums[left]) {
return left;
}
if (target == nums[right]) {
return right;
}
return -1;
}
};