力扣 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

---------------------------------------

题目是简单题,一看就知道这种题用二分查找即可。为了方便设置条件,可以设置左右两个指针规定要判断的范围。每次对两个指针中间的位置进行判定。如果中间版本错误,则选择左半范围继续查找;如果中间版本正确,则选择右半范围继续查找。但是我写出来的程序始终存在超时或者错误输出的问题

int firstBadVersion(int n) 
{
    bool state=false;
    int left=1,right=n;
    while(left!=right)
    {
        if(isBadVersion(1)==true)  //第一个就错
        {
            return left;
        }
        if( isBadVersion( left+(right-left)/2 ) ==false) //左右指针中间版本没错
        {
            left=left+(right-left)/2;
            continue;
        }
        else if( isBadVersion( left+(right-left)/2 ) ==true) //中间版本错了
        {
            right=left+(right-left)/2;
        }
    }
    return left;

以上为个人的写法,以下为正确的代码

int firstBadVersion(int n) {
    int left = 1, right = n;
    while (left < right) 
    {  // 循环直至区间左右端点相同
        int mid = left + (right - left) / 2;  // 防止计算时溢出
        if (isBadVersion(mid)) 
        {
            right = mid;  // 答案在区间 [left, mid] 中
        } 
        else 
        {
            left = mid + 1;  // 答案在区间 [mid+1, right] 中 //注意舍入问题导致+1
        }
    }
    // 此时有 left == right,区间缩为一个点,即为答案
    return left;
}

对比两端代码,可以发现基本思路都是一样的。但在一处细微的地方不一样:int型变量。奇数在减半后只保留整数部分,不做四舍五入。因此在区间减半后,如果是左半区间,不需要做额外调整。右半区间则需要额外给mid+1.此外,循环的判定条件也应该配合用小于号而不是不等号,用不等号可能导致严重问题,如程序跑飞。

posted @ 2022-03-15 18:23  namezhyp  阅读(14)  评论(0编辑  收藏  举报