题目:
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:
log n的解法想到二分法,二分法的关键在于每次去掉一半的数据
旋转有序数组总是有一半是升序的
如4 5 6 7 0 1 2 中左半边是有序的即4,5,6,7
如7 0 1 2 4 5 6 中右半边是有序的即2,4,5,6
我们可以通过查看mid < hi 来确定左半边有序还是右半边有序,如果小于,则右半边有序,否则左半边有序
确定是那部分有序后,我们就可以通过数组的有序性来判断target是否在有序数组中
- 假设右半部分有序即mid < hi
如果mid == target 直接返回mid
否则 我们判断 target是否在右边的有序数组中,将target与首尾元素相比较,即target > mid && target <= hi ,target已经明确不等于mid,故前面条件不用加等号,如果满足条件说明在右半边,左半边可以舍弃,即 lo = mid + 1,否则说明在左半边,右半边可以舍弃,即 hi = mid -1, - 假设左半部分有序即mid >= hi
如果mid == target 直接返回mid
否则 我们判断 target是否在左边的有序数组中,将target与首尾元素相比较,即target >= lo && target <mid,target已经明确不等于mid,故h后面条件不用加等号,如果满足条件说明在左半边,右半边可以舍弃,即hi = mid -1, 否则说明在右半边,左半边可以舍弃,即 lo = mid + 1,-1,
C++:
class Solution {
public:
int search(vector<int>& nums, int target) {
int lo = 0;
int hi = nums.size() - 1;
while(lo <= hi){
int mid = lo + (hi - lo) / 2;
if(nums[mid] == target) return mid;
if(nums[mid] < nums[hi]){
if(target > nums[mid] && target <= nums[hi]) lo = mid + 1;
else hi = mid -1;
} else {
if(target >= nums[lo] && target < nums[mid]) hi = mid - 1;
else lo = mid + 1;
}
}
return -1;
}
};
java:
class Solution {
public int search(int[] nums, int target) {
int lo = 0;
int hi = nums.length - 1;
while(lo <= hi){
int mid = lo + (hi - lo) / 2;
if(nums[mid]