We are playing the Guess Game. The game is as follows:
I pick a number from 1 to n. You have to guess which number I picked.
Every time you guess wrong, I'll tell you whether the number is higher or lower.
You call a pre-defined API guess(int num) which returns 3 possible results (-1, 1, or 0):-1 : My number is lower
1 : My number is higher
0 : Congrats! You got it!
递归二分查找
看完题目,我的第一想法是,递归二分查找。于是很快就写出如下代码。
Submit得到结果StackOverFlow,说明递归太深了。
public class Solution extends GuessGame {
public int guessNumber(int n) {
return guessNumberInternal(1, n);
}
private int guessNumberInternal(int left, int right) {
int middle = (left + right) / 2;
int result = guess(middle);
switch (result) {
case 1:
return guessNumberInternal(middle + 1, right);
case -1:
return guessNumberInternal(left, middle);
default:
return middle;
}
}
}
循环代替递归
那不能用递归做二分查找,能不能用循环来代替呢。
下面的代码Submit后,报错Time Limit Exceeded。擦居然超时了。
肉眼看代码检查了大半天,发现不粗破绽。
public class Solution extends GuessGame {
public int guessNumber(int n) {
int left = 1;
int right = n;
int guessNumber = 1;
while (left <= right) {
int middle = (left + right) / 2;
int result = guess(middle);
boolean find = false;
switch (result) {
case 1:
left = middle + 1;
break;
case -1:
right = middle - 1;
break;
default:
guessNumber = middle;
find = true;
break;
}
if (find) {
break;
}
}
return guessNumber;
}
}
超时原因,int
做加法时溢出了
在Java环境下,运行了上面的代码,才发现在计算middle
时候,left + right
这步计算int
溢出了。
最后,修改代码如下,Submit,终于Accepted了。
public class Solution extends GuessGame {
public int guessNumber(int n) {
int left = 1;
int right = n;
int guessNumber = 1;
while (left <= right) {
int middle = left + (right - left) / 2;
int result = guess(middle);
boolean find = false;
switch (result) {
case 1:
left = middle + 1;
break;
case -1:
right = middle - 1;
break;
default:
guessNumber = middle;
find = true;
break;
}
if (find) {
break;
}
}
return guessNumber;
}
}