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.
Your algorithm's runtime complexity must be in the order of O(log n).
Example 1:
Input: nums = [4,5,6,7,0,1,2]
, target = 0
Output: 4
Example 2:
Input: nums = [4,5,6,7,0,1,2]
, target = 3 Output: -1
法1:将数组一分为二,其中一定有一个是有序的,另一个可能是有序,也能是部分有序。此时有序部分用二分法查找。无序部分再一分为二,其中一个一定有序,另一个可能有序,可能无序。就这样循环.
class Solution { public: int search(vector<int>& nums, int target) { int low = 0; int high = nums.size() - 1; while(low <= high) { int mid = low + (high - low)/2; if (nums[mid] == target) return mid; if (nums[low] <= nums[mid]) { // the left is sorted if (nums[low] <= target && target <= nums[mid]) { // target is in the left high = mid - 1; // go to the left to search } else { // target is in hte right low = mid + 1; // go to the right to search } } else { // the right is sorted if (nums[mid] <= target && target <= nums[high]) { // target is in the right low = mid + 1; //go to the right to search } else { // target is in the left high = mid - 1; //go to the left to search } } } return -1; } };
从左向右,如果左边的点比右边的点小,说明这两个点之间是有序的。
如果左边的点比右边的点大,说明中间有个旋转点,所以一分为二后,肯定有一半是有序的。所以还可以用二分法。
不过先要判断左边有序还是右边有序,如果左边有序,则直接将目标与左边的边界比较,就知道目标在不在左边,
如果不在左边肯定在右边。
1 class Solution { 2 public int search(int[] a, int target) { 3 int n = a.length; 4 int lo = 0; 5 int hi = n - 1; 6 while(lo<=hi){ 7 int mid = lo+(hi-lo)/2; 8 if(a[mid]== target) 9 return mid; 10 11 if(a[lo]<=a[mid]){//左半边有序 12 if(a[lo]<=target && target<=a[mid])//目标值在左半边 13 hi = mid - 1; 14 else 15 lo = mid + 1; 16 } 17 else{//右半边有序 18 if(a[mid]<=target && target<=a[hi]) 19 lo = mid + 1; 20 else 21 hi = mid - 1; 22 } 23 } 24 return -1; 25 26 } 27 }