算法专题(01)二分查找(03) 简单LeetCode 278
Posted 英雄哪里出来
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法专题(01)二分查找(03) 简单LeetCode 278相关的知识,希望对你有一定的参考价值。
一、题目
1、题目描述
软件开发的时候,会有版本的概念。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。假设你有 n n n 个版本 [ 1 , 2 , . . . , n ] [1, 2, ..., n] [1,2,...,n],你想找出导致之后所有版本出错的第一个错误的版本。可以通过调用
bool isBadVersion(version)
接口来判断版本号version
是否在单元测试中出错。实现一个函数来查找第一个错误的版本。应该尽量减少对调用 API 的次数。
样例: 5 5 5 和 b a d = 4 bad = 4 bad=4,输出 4 4 4;
2、基础框架
- c++ 版本给出的基础框架代码如下,其中
bool isBadVersion(int version)
是供你调用的 API,也就是当你调用这个 API 时,如果version
是错误的,则返回true
;否则,返回false
;
// The API isBadVersion is defined for you.
// bool isBadVersion(int version);
class Solution {
public:
int firstBadVersion(int n) {
}
};
3、原题链接
二、解题报告
1、思路分析
- 由题意可得,我们调用它提供的 API 时,返回值分布如下:
- 000...000111...111 000...000111...111 000...000111...111
- 其中 0 代表
false
,1 代表true
;也就是一旦出现 1,就再也不会出现 0 了。 - 所以基于这思路,我们可以二分位置;
归纳总结为 2 种情况,如下:
1)当前二分到的位置 m i d mid mid,给出的版本是错误,那么从当前位置以后的版本不需要再检测了(因为一定也是错误的),并且我们可以肯定,出错的位置一定在 [ l , m i d ] [l, mid] [l,mid];并且 m i d mid mid 是一个可行解,记录下来;
2)当前二分到的位置 m i d mid mid,给出的版本是正确,则出错位置可能在 [ m i d + 1 , r ] [mid+1, r] [mid+1,r];
2、时间复杂度
- 由于每次都是将区间折半,所以时间复杂度为 O ( l o g 2 n ) O(log_2n) O(log2n)。
3、代码详解
// The API isBadVersion is defined for you.
// bool isBadVersion(int version);
class Solution {
public:
int firstBadVersion(int n) {
long long l = 1, r = n; // (1)
long long ans = (long long)n + 1;
while(l <= r) {
long long mid = (l + r) / 2;
if( isBadVersion(mid) ) {
ans = mid; // (2)
r = mid - 1;
}else {
l = mid + 1; // (3)
}
}
return ans;
}
};
-
(
1
)
(1)
(1) 需要这里,这里两个区间相加可能超过
int
,所以需要采用 64 位整型long long
; - ( 2 ) (2) (2) 找到错误版本的嫌疑区间 [ l , m i d ] [l, mid] [l,mid],并且 m i d mid mid 是确定的候选嫌疑位置;
- ( 3 ) (3) (3) 错误版本不可能落在 [ l , m i d ] [l, mid] [l,mid],所以可能在 [ m i d + 1 , r ] [mid+1, r] [mid+1,r],需要继续二分迭代;
三、本题小知识
二分时,如果区间范围过大,
int
难以招架时,需要动用long long
;
以上是关于算法专题(01)二分查找(03) 简单LeetCode 278的主要内容,如果未能解决你的问题,请参考以下文章
算法专题(01)二分查找(02) 简单LeetCode 35