public class Solution extends VersionControl {
public int firstBadVersion(int n) {
int left = 1;
int right = n;
while(left + 1 < right){
int mid = left + (right - left) / 2;
if(isBadVersion(mid)){
right = mid;
} else {
left = mid;
}
}
if(isBadVersion(left)) return left;
else if(isBadVersion(right)) return right;
return -1;
}
}
在把上一道题做完之后,这题就是一个乞丐版的 search in rotated sorted array. 因为已知没有 duplicates 就更简单了。
public class Solution {
public int findMin(int[] nums) {
int left = 0;
int right = nums.length - 1;
while(left + 1 < right){
int mid = left + (right - left) / 2;
if(nums[mid] >= nums[right]){
left = mid;
} else {
right = mid;
}
}
return Math.min(nums[left], nums[right]);
}
}
加上有重复元素的条件之后,这题立刻就变成 Hard 难度了。原因在于出现了新情况,即我们不知道最小值到底在 mid 的左边还是右边,比如【3,[3],1,3】,中间的 3 和两端值都相等,无法正确地直接砍掉一半。
我们依然可以靠 A[mid] 与 A[right] 的大小关系来二分搜索;
A[mid] > A[right] 时,mid 在左半边,最小值一定在 mid 右侧;
A[mid] < A[right] 时,mid 在右半边,最小值一定在 mid 左侧;
A[mid] == A[right] 时,无法判断,把 right 向左挪一格。
public class Solution {
public int findMin(int[] nums) {
int left = 0;
int right = nums.length - 1;
while(left + 1 < right){
int mid = left + (right - left) / 2;
if(nums[mid] > nums[right]){
left = mid;
} else if(nums[mid] < nums[right]){
right = mid;
} else {
right --;
}
}
return Math.min(nums[left], nums[right]);
}
}