算法题目:
你是产品经理,目前正在带领一个团队开发新的产品。
不幸的是,你的产品的最新版本没有通过质量检测。
由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
假设你有 n 个版本 [1, 2, ..., n],你想找出导致之后所有版本出错的第一个错误的版本。
你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。
实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
示例:
给定 n = 5,并且 version = 4 是第一个错误的版本。
调用 isBadVersion(3) -> false
调用 isBadVersion(5) -> true
调用 isBadVersion(4) -> true
所以,4 是第一个错误的版本。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/first-bad-version
猛一看题目这么简单,洋洋洒洒的写完了。
public class Solution extends VersionControl {
public int firstBadVersion(int n) {
int left = 1, right = n;
while(left < right){
int mid = (right + left) / 2;
if (isBadVersion(mid)){
right = mid;
}
else {
left = mid + 1;
}
}
return left;
}
}
当我信心满满提交的时候,返回的却是运行失败。但在我反复检查之后也没有发现错误的地方。
运行失败:
Time Limit Exceeded
测试用例:2126753390
1702766719
Why? 大写的WHY?
解析:
须知:Integer都有自己的表示范围,他有定义 MAX_VALUE
和 MIN_VALUE
/**
* A constant holding the minimum value an {@code int} can
* have, -2<sup>31</sup>.
*/
@Native public static final int MIN_VALUE = 0x80000000;
/**
* A constant holding the maximum value an {@code int} can
* have, 2<sup>31</sup>-1.
*/
@Native public static final int MAX_VALUE = 0x7fffffff;
当我们的数超过他所规定的最值时,Integer将无法表示。
因此在我们上述算法中,
left <= MAX_VALUE和 right <= MAX_VALUE是肯定的, 但是left+right <= MAX_INT 我们无法确定,所以会造成栈溢出
那么知道问题所在,我们怎么修改我们的代码呢?
我们可以使用
int mid = left + (right - left) /2;
来代替
int mid = (right + left) / 2;