278.第一个错误的版本
标签: binary-search
难度: Easy
通过率: 45.26%
原题链接: https://leetcode.com/problems/first-bad-version/description/
题目描述
你是一个产品经理并正在领导一个团队开发新产品。不幸的是,你的产品中的某个版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以之后的所有版本都是错误的。假设有 个版本 ,你想要找出第一个出错的版本。你可以调用一个 API isBadVersion(version)
来判断版本是否错误。实现一个函数来找到第一个错误的版本,尽量减少对 API 的调用次数。
解题思路
要找到第一个错误的版本,我们可以利用二分查找来减少对 API 的调用次数。我们将版本范围 作为搜索空间。每次检查中点版本: 如果这个版本是错误的,那么第一个错误版本一定在中点之前或是中点;如果不是错误的,那么第一个错误版本一定在中点之后。通过不断缩小搜索区间,我们可以高效地找到第一个错误版本。
代码实现
- Python
- C++
- JavaScript
- Java
def firstBadVersion(n):
# 二分查找初始化
left, right = 1, n
while left < right:
# 找到中点
mid = left + (right - left) // 2
# 检查中点版本是否错误
if isBadVersion(mid):
# 中点版本错误,搜索区间改为[left, mid]
right = mid
else:
# 否则搜索区间改为[mid + 1, right]
left = mid + 1
# 当left==right时,第一个错误版本即为left或right
return left
int firstBadVersion(int n) {
int left = 1, right = n;
while (left < right) {
// 使用防止溢出的方式计算中点
int mid = left + (right - left) / 2;
if (isBadVersion(mid)) {
// 中点版本错误,搜索区间为[left, mid]
right = mid;
} else {
// 否则搜索区间为[mid + 1, right]
left = mid + 1;
}
}
// left == right时,即找到第一个错误版本
return left;
}
/**
* @param {number} n
* @return {number}
*/
var firstBadVersion = function(n) {
let left = 1, right = n;
while (left < right) {
// 计算中点
const mid = Math.floor(left + (right - left) / 2);
if (isBadVersion(mid)) {
// 中点版本是错误的,那么错误版本在[left, mid]
right = mid;
} else {
// 否则在[mid + 1, right]
left = mid + 1;
}
}
// 第一个错误版本
return left;
};
public class Solution {
public int firstBadVersion(int n) {
int left = 1, right = n;
while (left < right) {
// 防止加法溢出
int mid = left + (right - left) / 2;
if (isBadVersion(mid)) {
// 中点版本是错误的,搜索区间为[left, mid]
right = mid;
} else {
// 否则搜索区间为[mid + 1, right]
left = mid + 1;
}
}
// 当left == right时,第一个错误版本即为left或right
return left;
}
}
复杂度分析
时间复杂度为 ,因为我们使用二分查找,每次将搜索空间减半。
空间复杂度为 ,因为只需要常数个额外变量来进行计算和存储结果。