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.
如果是一个未经旋转的有序数组,显然可以直接用二分查找来做。经过旋转的数组,其实本质就是两个排序数组,我们可以分别在两个数组中进行二分查找,难点是找到两个数组的分界线,用遍历的方式来寻找分界线复杂度为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; } };
以上的方案我们通过寻找两个排序数组的分界线,从而对其分别使用二分查找来完成搜索。实际上,该题不必如此繁琐,我们可以省去寻找分界线的步骤,直接进行二分查找。代码如下:
// 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; } };