题目描述:
你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
假设你有 n 个版本 [1, 2, …, n],你想找出导致之后所有版本出错的第一个错误的版本。
你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
示例1:
输入:n = 5, bad = 4
输出:4
解释:
调用 isBadVersion(3) -> false
调用 isBadVersion(5) -> true
调用 isBadVersion(4) -> true
所以,4 是第一个错误的版本。
示例2:
输出:n = 1, bad = 1
输出:1
解题思路:
首先我们应先对题目有一个解读分析,本题目让我们返回第一个错误得到版本,并且如果第一版本错误那么后面的版本就都是错误的,所以我们可以将问题抽象为在一部分有序相连由true和false元素组成的数组中返回第一次出现false的位置!所以我们可以明确此题目是一个查找类型的题目,加上部分相连有序的特点我们可以用二分查找来实现!但是此题目较最为常见的二分查找题目操作又有一点差别,但还是用到了二分思想!!!先上代码,最后看详细解读和图示!!!
代码:
public class Solution extends VersionControl {
//Binary Search
//Time Complexity: O(N)
//Space Complexity: (1)
public int firstBadVersion(int n) {
//定义前后指针
int start = 0;
int end = n;
//start需要小于end
while (start < end) {
//防止超出整型数范围
int mid = start + (end - start) / 2;
if (!(isBadVersion(mid))) {
//start 移动到mid + 1位置
start = mid + 1;
} else {
//end 移动到mid位置
end = mid;
}
}
//返回start or end
return start;
}
}
部分代码操作解读:
1.为什么while循环里必须start < end而不能是start <= end?
2为社么此处mid = start + (end - start) / 2
3.为什么start 移动到mid + 1,而end移动到mid
4.为什么最后返回start和end都行
解读:
1.因为我们在二分查找的过程中会出现这样一种请况start和end指向同一个值并且此时这个它们同时指向的元素为false这个时候由于对于end指针的移动规则(end = mid)会导致出现死循环!!!
2.此处防止数据超出整形范围!!!
3.由于这个问题的特性,由false组成的元素在true组成的元素的后面,所以但我们第二分查找到的元素为true时则说明表示false的元素在mid的后面,所以我们直接让start移动到mid + 1,但是对于end指针,我们当我们二分查找到的元素为false时,则表示此时mid处的元素一定为false但是mid左处的元素也有可能为fasle,由于题目要返回第一个为false的位置,所以将end移动到mid处。
4.由于本题目start和end移动的特点,其实最后退出循环时start和end指向同一个位置,所以返回start和end都行!!!
图示: