LeetCode 278. 第一个错误的版本

题目:

你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。

假设你有 n 个版本 [1, 2, …, n],你想找出导致之后所有版本出错的第一个错误的版本。

你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。

解答:

// The API isBadVersion is defined for you.
// bool isBadVersion(int version);

class Solution {
public:
    int firstBadVersion(int n) 
    {
        //找前面是正确的错误编号
        long long left = 1, right = n;
        while(left <= right)
        {
            long long mid = (left + right)/2;
            cout<<isBadVersion(0)<<endl;
            cout<<isBadVersion(1)<<endl;
            cout<<isBadVersion(2)<<endl;
            if (isBadVersion(mid) && (!isBadVersion(mid - 1)))//isBadVersion()接口对于传入的参数做了处理,此处如果mid-1==0,会返回(被认为是正确版本),所以可以放心用不会溢出
            /* 此处if判断的正确条件是:
             *     mid是 错误版本,mid前一个是 正确版本
             * 检验mid = 1特殊值:mid = 1肯定是left = 1,right = 2 或 left = 1,right = 1的时候.
             * 假设left = 1, right = 2:若版本1是错的,mid = 1;会满足第一个if,最终输出1;若版本2是错的,会满足第三个if,left变成2,最终输出2
             * 假设left = 1, right = 1,版本1是错的,版本0是对的(isBadVersion对于0处理的特性)会满足第一个if
            */
                return mid;
            else if (isBadVersion(mid) && isBadVersion(mid - 1))//太靠后
                right = mid - 1;
            else 
                left = mid + 1;
        }
        return 0;
    }
};

总结

最近一周在做二分查找的专项训练,这个题是接着上个二分查找做的。这个题没有直接给mid=一个值,而是给了一个mid的判断条件。
该题有几个学习到的知识点:

  1. 溢出的问题。我是直接用long long 做了,但是看到评论区解决问题的方法还有mid = left + (right - left)/2,或者使用右移运算符>>,写成mid=(left+right)>>1,mid=(left+right)>>1相当于mid=(left+right)/2,但是比除2运算要快。
  2. 有人在讨论等号问题,但是由于二分有好几种写法,先这样写,看看后面还有没有什么题对这个等号有限制

你可能感兴趣的:(leetcode,leetcode,算法)