278. 第一个错误的版本
你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
假设你有 n
个版本 [1, 2, ..., n]
,你想找出导致之后所有版本出错的第一个错误的版本。
你可以通过调用 bool isBadVersion(version)
接口来判断版本号 version
是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
示例:
给定 n = 5,并且 version = 4 是第一个错误的版本。
调用 isBadVersion(3) -> false
调用 isBadVersion(5) -> true
调用 isBadVersion(4) -> true
所以,4 是第一个错误的版本。
思路:
最朴素直观的做法就是从头遍历所有的版本,时间复杂度是 O ( n ) O(n) O(n),但题目要求尽量减少对API的调用次数,所以我们应该用更高效的方法。
联想到二分的本质:“一个问题是否满足二段性”。显然本问题满足,调用isBadVersion(mid)只会返回两种结果,要么false,要么true,可以将所有的版本分为红色和绿色两个部分,红色表示能通过质量检测的版本,绿色表示不能通过质量检测的版本 ,如下图,我们只需要找到绿色区域的起点即可,二分时间复杂度 O ( l o g n ) O(logn) O(logn)。
要注意的点:
当n
是Intger.MAX_VALUE
的时候,mid = l + r >> 1
中的l + r
可能越界,故我们应该写成mid = l + (r - l)/2
Java代码
/* The isBadVersion API is defined in the parent class VersionControl.
boolean isBadVersion(int version); */
public class Solution extends VersionControl {
public int firstBadVersion(int n) {
int l = 1, r = n;//题目给的版本从1~n
while(l < r){
int mid = l + (r-l)/2;
//若mid是坏版本,则它之后的版本都是坏的,故第一个坏的版本会在[l,mid]区间内
if(isBadVersion(mid)) r = mid;
else l = mid + 1;
}
return l;
}
}