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) {
if(nums.size()==0) return -1;
return bt_search(nums, 0,nums.size()-1,target);
}
int bt_search(vector<int>& a, int low, int high, int target) {
int mid = low + (high - low) / 2;
if(a[low]==target) return low;
if(a[high]==target) return high;
if(low>=high) return -1;
if (a[low] < a[mid]) {
if (a[low] <target && target< a[mid]) {
return bt_search(a, low+1, mid-1, target);
}
else {
return bt_search(a,mid, high, target);
}
} else {
if (a[mid] <target && target <a[high]) {
return bt_search(a, mid+1, high-1, target);
}
else {
return bt_search(a,low, mid, target);
}
}
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 }
