LeetCode 278. First Bad Version

来源:互联网 发布:什么叫编程语言 编辑:程序博客网 时间:2024/04/29 07:52

题目

You are a product manager and currently leading a team to develop a new product. Unfortunately, the latest version of your product fails the quality check. Since each version is developed based on the previous version, all the versions after a bad version are also bad.

Suppose you have n versions [1, 2, …, n] and you want to find out the first bad one, which causes all the following ones to be bad.

You are given an API bool isBadVersion(version) which will return whether version is bad. Implement a function to find the first bad version. You should minimize the number of calls to the API.

分析

我们先从二分查找说起. 一个简单的二分查找示例是从一个一维数组中查找某个数字 x , 若存在, 返回其下标; 若不存在, 返回非法下标-1.

代码如下:

int binsearch(int nums[], int len, int target) {    int lo = 0, hi = len, mid;    while (lo < hi) {        mid = lo + ((hi - lo) >> 1);        if (nums[mid] == target) {            return mid;        }        else if (nums[mid] > target) {            hi = mid;        }        else {            lo = mid + 1;        }    }    return -1;}

如果你经常忘记 while 内的判定条件, 或者 hilo 的改变方式, 那么下面的分析或许可以帮到你. 初始时, 我们要查找的 x 可能存在于[lo, hi)限定的数组范围内. 这是一个左闭右开区间, 即 x 可能是 nums[lo], 但绝不可能是 nums[hi]. 正应如此, while 中的条件应该是 lo < hi, 若不满足条件说明x不在数组内. 循环内每次计算mid, 然后对比nums[mid]target, 若相同, 则返回mid; 若nums[mid]较大, 则target只可能在[lo, mid)中, 因此令hi = mid; 否则, target只能在(lo, hi), 即[lo+1, hi]中, 因此令lo = mid + 1.

在此过程中, lo始终为可能的最小下标, hi始终比可能的最大下标大1.

将本题与上面的分析类比, 不难得出以下代码. 需要注意的是, 这里的所谓找到数字, 就是找到某一mid使其满足以下两条件之一:

  • isBadVersion(mid)true, 而isBadVersion(mid-1)false
  • isBadVersion(mid)truemid == 1
// Forward declaration of isBadVersion API.bool isBadVersion(int version);class Solution {public:    int firstBadVersion(int n) {        int lo = 1, hi = n+1;        while (lo < hi) {            int mid = lo + ((hi - lo) >> 2);            if (isBadVersion(mid)) {                if (mid == 1 || !isBadVersion(mid - 1)) {                    return mid;                }                else {                    hi = mid;                }            }            else {                lo = mid + 1;            }        }        cout << "Won't be here" << endl;        return -1;    }};

然而提交后的结果是:

错误结果

错误的原因是以2147483647作为输入, hi = n + 1导致结果超出int所能表示的最大正整数, 因此在while第一次测试条件时就跳过了循环. 我们对代码进行修正, 让hi指向可能的 最大下标, 因此while中条件判断也要作出修改, 因为此时lo == hi也可能得出满足条件的mid.

解答

// Forward declaration of isBadVersion API.bool isBadVersion(int version);class Solution {public:    int firstBadVersion(int n) {        int lo = 1, hi = n;        while (lo <= hi) { // 注意!            int mid = lo + ((hi - lo) >> 2);            if (isBadVersion(mid)) {                if (mid == 1 || !isBadVersion(mid - 1)) {                    return mid;                }                else {                    hi = mid;                }            }            else {                lo = mid + 1;            }        }        cout << "Won't be here" << endl;        return -1;    }};
0 0