文章目录
- 题目
- 标题和出处
- 难度
- 题目描述
- 要求
- 示例
- 数据范围
- 解法
- 思路和算法
- 代码
- 复杂度分析
题目
标题和出处
标题:第一个错误的版本
出处:278. 第一个错误的版本
难度
3 级
题目描述
要求
你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错误的。
假设你有 n \texttt{n} n 个版本 [1, 2, ..., n] \texttt{[1, 2, ..., n]} [1, 2, ..., n],你想找出导致之后所有版本出错的第一个错误的版本。
你可以通过调用接口 bool isBadVersion(version) \texttt{bool isBadVersion(version)} bool isBadVersion(version) 判断版本号 version \texttt{version} version 是否在单元测试中出错。实现一个函数查找第一个错误的版本。你应该尽量减少调用接口的次数。
示例
示例 1:
输入: n = 5, bad = 4 \texttt{n = 5, bad = 4} n = 5, bad = 4
输出: 4 \texttt{4} 4
解释:
调用 isBadVersion(3) → false \texttt{isBadVersion(3)} \rightarrow \texttt{false} isBadVersion(3)→false
调用 isBadVersion(5) → true \texttt{isBadVersion(5)} \rightarrow \texttt{true} isBadVersion(5)→true
调用 isBadVersion(4) → true \texttt{isBadVersion(4)} \rightarrow \texttt{true} isBadVersion(4)→true
所以, 4 \texttt{4} 4 是第一个错误的版本。
示例 2:
输入: n = 1, bad = 1 \texttt{n = 1, bad = 1} n = 1, bad = 1
输出: 1 \texttt{1} 1
数据范围
- 1 ≤ bad ≤ n ≤ 2 31 − 1 \texttt{1} \le \texttt{bad} \le \texttt{n} \le \texttt{2}^\texttt{31} - \texttt{1} 1≤bad≤n≤231−1
解法
思路和算法
用 bad \textit{bad} bad 表示第一个错误的版本。对于某个在范围 [ 1 , n ] [1, n] [1,n] 中的版本,使用该版本调用接口得到结果。如果该版本是错误的,则 bad \textit{bad} bad 小于等于该版本;如果该版本是正确的,则 bad \textit{bad} bad 大于该版本。由于可以根据调用接口的结果缩小查找范围,因此可以使用二分查找得到 bad \textit{bad} bad。
由于 bad \textit{bad} bad 一定在范围 [ 1 , n ] [1, n] [1,n] 内,因此初始时二分查找的范围的下界和上界是 low = 1 \textit{low} = 1 low=1, high = n \textit{high} = n high=n。
每次查找时,取 mid \textit{mid} mid 为 low \textit{low} low 和 high \textit{high} high 的平均数向下取整,对 mid \textit{mid} mid 调用接口,根据结果调整二分查找的范围。
-
如果 mid \textit{mid} mid 是错误的,则 bad \textit{bad} bad 小于等于 mid \textit{mid} mid,因此在范围 [ low , mid ] [\textit{low}, \textit{mid}] [low,mid] 中继续查找。
-
如果 mid \textit{mid} mid 是正确的,则 bad \textit{bad} bad 大于 mid \textit{mid} mid,因此在范围 [ mid + 1 , high ] [\textit{mid} + 1, \textit{high}] [mid+1,high] 中继续查找。
当 low = high \textit{low} = \textit{high} low=high 时,结束查找,此时 low \textit{low} low 即为 bad \textit{bad} bad,返回 low \textit{low} low。
代码
public class Solution extends VersionControl {public int firstBadVersion(int n) {int low = 1, high = n;while (low < high) {int mid = low + (high - low) / 2;if (isBadVersion(mid)) {high = mid;} else {low = mid + 1;}}return low;}
}
复杂度分析
-
时间复杂度: O ( log n ) O(\log n) O(logn)。二分查找的次数是 O ( log n ) O(\log n) O(logn),每次查找的时间是 O ( 1 ) O(1) O(1),时间复杂度是 O ( log n ) O(\log n) O(logn)。
-
空间复杂度: O ( 1 ) O(1) O(1)。