1. Binary Search--704
要求O(logn) run time complexity ->想到二分法这样就会是O(logn). 另外要想到有两个pointer,left right来定位什么时候end loop
2. First Bad Version--278
第一想法就是loop through n and find the min of n that isBadVersion(n) is true. In this case, the time Complexity will be O(n). It will result Time Limit Exceeded. So which should I do to improve the time complexity given the hint that I could use binary search?
/* The isBadVersion API is defined in the parent class VersionControl.
boolean isBadVersion(int version); */
public class Solution extends VersionControl {
public int firstBadVersion(int n) {
int left = 1;
int right = n;
int result = n;
while(left < right){
int middle = (left+right)/2;
if(isBadVersion(middle) == false){
left = middle;
}else if(isBadVersion(middle) == true){
if(isBadVersion(middle-1) == true){
right = middle;
}else if (isBadVersion(middle-1) == false){
result = middle;
}
}
}
return result;
}
}
问题出在
1. 应该是left = middle-1而不是left = middle。 left = middle会造成infinity loop因为left一直是一样的,middle不变
2.不需要去判断isBadVersion(middle-1) == true因为最后left和right会相等落在true那里,return其中一个就好。 result就是middle=left=right
/* The isBadVersion API is defined in the parent class VersionControl.
boolean isBadVersion(int version); */
public class Solution extends VersionControl {
public int firstBadVersion(int n) {
int left = 1;
int right = n;
while(left < right){
int middle = (left+right)/2;
if(isBadVersion(middle) == false){
left = middle + 1;
}else{
right = middle;
}
}
return left;
}
}
这个方法依然超时,问题是什么呢?test case里面会造成Integer Overflow
1. Integer Overflow
In Java, the int type has a fixed range of values it can represent, from -2^31 to 2^31 - 1. If left and right are both very large integers close to 2^31 - 1, adding them together could cause the sum to wrap around to a negative number, resulting in an incorrect value for middle. This is known as integer overflow.
2. Safe Middle Calculation
By calculating middle with left + (right - left) / 2, you avoid this potential overflow because (right - left) will always be a non-negative number that fits within the range of int, assuming right is greater than left. The addition of left afterwards also stays within the bounds of the int range.
所以middle = (left+right)/2 在java是保证正确的,应该用middle=left + (right - left) / 2
最终正确版:
/* The isBadVersion API is defined in the parent class VersionControl.
boolean isBadVersion(int version); */
public class Solution extends VersionControl {
public int firstBadVersion(int n) {
int left = 1;
int right = n;
while (left < right) {
int mid = left + (right - left) / 2;
if (isBadVersion(mid)) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
}