听风是风

学或不学,知识都在那里,只增不减。

导航

JS Leetcode 278. 第一个错误的版本 题解分析

壹 ❀ 引

本题来自LeetCode的278. 第一个错误的版本,难度简单,端午节就应该做点容易的题目缓解心情,题目描述如下:

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

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

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

示例:

给定 n = 5,并且 version = 4 是第一个错误的版本。

调用 isBadVersion(3) -> false
调用 isBadVersion(5) -> true
调用 isBadVersion(4) -> true

所以,4 是第一个错误的版本。

我们简单分析题意,然后来实现它。

贰 ❀ 二分法思路

根据题意,我们假定有了一个能判断当前版本是否是错误版本的API方法isBadVersion,现在要求,尽可能少的调用它,然后找出最早出现错误的问题版本。假设给定的版本是n,如果我们不考虑性能,当然可以从1遍历到n,以此检验,当第一个isBadVersion(i)true时,那说明i就是最早出现的问题版本,当然这样做很明显就不符合要求了。

由于题目也提到,当一个版本出现问题时,那么它之后的版本一定都出现问题。而当一个版本出现问题时,它之前可能有一部分版本也有问题,因此我们完全可以根据二分法,来实现此题。

我们假定有[1,2,3,4,5]五个版本,而最早出现问题的版本是2,那么根据二分法性质,我们可以一开始就检验中间的版本,因为isBadVersion(3)true,可以得知右侧的版本都有问题,我们可以转移左边界,需要注意的是,我们接下来需要继续搜索[1,2,3],因为可能3也有可能是最早的错误版本,所以肯定不能立刻排除3。但如果最早错误版本是4,而isBadVersion(4)false,那么我们接下来需要检索的是[4,5],因为3不是错误版本就没必要参与下次排查了,这是左右边界需要注意的地方。

让我们来实现这段代码:

/**
 * @param {function} isBadVersion()
 * @return {function}
 */
var solution = function (isBadVersion) {
    /**
     * @param {integer} n Total versions
     * @return {integer} The first bad version
     */
    return function (n) {
        // 定义左右初始指针
        let l = 1, r = n;
        while (l < r) {
            // 防止计算时溢出
            const mid = Math.floor(l + (r - l) / 2);
            if (isBadVersion(mid)) {
                //更新右边界
                r = mid; 
            } else {
                //更新左边界,为什么加1文中也说了
                l = mid + 1;
            }
        };
        return l;
    };
};

posted on 2021-06-14 00:02  听风是风  阅读(172)  评论(0编辑  收藏  举报