您的位置:首页 > 其它

LeetCode 278. First Bad Version

2016-04-07 22:27 507 查看

题目

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
内的判定条件, 或者
hi
lo
的改变方式, 那么下面的分析或许可以帮到你. 初始时, 我们要查找的
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)
true
mid == 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;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode