![]()
![]()
- 翻转点在前半部分 nums[mid]<=nums[low]
- 而后半部分是单调递增的,比较好判断。可以判断如果 nums[mid] < target <= nums[high] ,去后半部分
- else 去后半部分
- else 翻转点在后半部分 nums[mid]>nums[low]
- 而前半部分是单调递增的,比较好判断。可以判断如果 nums[low] <= target < nums[mid], 去前半部分
- else 去前半部分
class Solution {
public int search(int[] nums, int target) {
int low =0;
int high = nums.length-1;
// 注意条件是 low<=high
while(low <= high) {
// [3,1] target 是 1 的情况,如果这里没有 +1,low,mid是0,那high=mid-1就是-1了
int mid = low + (high - low + 1)/2;
if (target == nums[mid]) {
return mid;
}
// 翻转点在前半部分。后半部分是单调递增的
if (nums[mid] < nums[low]) {
// 后半部分是单调递增的。这里是去后半部分的情况
if (target > nums[mid] && target <= nums[high]) {
// 前面 if (target == nums[mid]) 就返回了,所以这里可以排除 mid
low = mid+1;
}
else {
// 前面 if (target == nums[mid]) 就返回了,所以这里可以排除 mid
high = mid-1;
}
}
// 翻转点在后半部分+正好在中点。前半部分是单调递增的。
else {
// 前半部分是单调递增的。这里是去前半部分的情况
if (target >= nums[low] && target< nums[mid]) {
high = mid - 1;
}
else {
low = mid + 1;
}
}
}
return -1;
}
}
class Solution {
public int findMin(int[] nums) {
int low = 0;
int high = nums.length - 1;
while(low<=high) {
int mid = low + (high - low)/2;
// 初始时是全部,一定不是一个单调增区间
// 后面一直往有翻转点的区间走
if (nums[low] <= nums[high]) {
return nums[low];
}
// 最小值一定在翻转点所在的区间。
// 翻转点在前半部分,去前半部分
if (nums[mid]<nums[low]) {
// int mid = low + (high - low)/2; 比如1.5要算成1,因此要弥补前半部分。这里不用-1
high = mid;
}
// 否则翻转点在后半部分,去后半部分
else {
// int mid = low + (high - low)/2; 比如1.5要算成1,因此要用后半部分弥补前半部分。这里要+1
low = mid+1;
}
}
return -1;
}
}