欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

278. 第一个错误的版本

程序员文章站 2024-03-17 17:05:34
...

278. 第一个错误的版本

1.题目描述

你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
假设你有 n 个版本 [1, 2, …, n],你想找出导致之后所有版本出错的第一个错误的版本。
你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
示例:
278. 第一个错误的版本

2.思路(二分法)

场景一:isBadVersion(mid) => false

1 2 3 4 5 6 7 8 9
G G G G G G B B B G = 正确版本,B = 错误版本
| | |
left mid right
场景一中,isBadVersion(mid) 返回 false,因此我们知道 mid 左侧(包括自身)的所有版本都是正确的。所以我们令 left=mid+1,把下一次的搜索空间变为 [mid+1,right]。
场景二:isBadVersion(mid) => true

1 2 3 4 5 6 7 8 9
G G G B B B B B B G = 正确版本,B = 错误版本
| | |
left mid right
场景二中,isBadVersion(mid) 返回 true,因此我们知道 mid 右侧(不包括自身)的所有版本的不可能是第一个错误的版本。所以我们令 right=mid,把下一次的搜索空间变为[left,mid]。当某一次操作后,left和right 的值相等,此时它们就表示了第一个错误版本的位置。可以用数学归纳法 证明 二分查找算法的正确性。

3.代码

// Forward declaration of isBadVersion API.
bool isBadVersion(int version);

class Solution {
public:
    int firstBadVersion(int n) {
        int left = 0, right = n;
        while(left < right){
            int mid = left + (right - left) / 2;
            if(isBadVersion(mid)){
                right = mid;
            }
            else{
                left = mid + 1;
            }
        }
        return left;
    }
};

4.复杂度分析

时间复杂度:O(logn)
空间复杂度:O(1)