题目描述
题目链接:278.第一个错误的版本
你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
假设你有n
个版本 [1, 2, ..., n]
,你想找出导致之后所有版本出错的第一个错误的版本。
你可以通过调用bool isBadVersion(version)
接口来判断版本号version
是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
示例 1
输入:n = 5, bad = 4
输出:4
解释:
调用isBadVersion(3)
-> false
调用isBadVersion(5)
-> true
调用isBadVersion(4)
-> true
所以,4 是第一个错误的版本。
示例 2
输入:n = 1, bad = 1
输出:1
提示
- 1 <= bad <= n <= 231 - 1
解题核心
本题核心就是确定位置,实际上就是一个查找算法设计,唯一一点不同的就是查找的其实是一个长度为2的区间
,前一个位置为false
,后一个位置为true
解法一:二分查找
(本来我以为官方会有什么高级的算法,结果和我一样只写了二分)
public int firstBadVersion(int n) {
int left = 1;
int right = n;
int middle = 0;
while (left < right) {
middle = (right - left) >> 1 +left;
if (isBadVersion(middle) && !isBadVersion(middle - 1)) {
break;//这里强行限制了两个位置的结果
} else if (isBadVersion(middle)) {
right = middle - 1;
} else {
left = middle + 1;
}
}
return middle;
}
优化一下就是下面的写法,当middle
的结果为true
的时候,右边界在不断向左移动(因为不确定前一个位置的结果,所以移动的时候不能直接跳到前一个位置),直到middle
的结果为false
的时候,左边界开始向右移动,最终会使得两个边界刚好就是这个长度为2的区间
边界,下一次判断会使得left == right
然后跳出循环
public int firstBadVersion2(int n) {
int left = 1;
int right = n;
int middle = 0;
while (left < right){
middle = left + ((right - left) >> 1);
if(isBadVersion(middle)) {
right = middle;//并不知道前一个版本是否是正确的
} else {
left = middle + 1;
}
}
return left;
}