题意是这样的:
大致的意思就是会给出一个n,然后在[1, n]中间挑一个数,题目会给一个方法guess(int num)来帮助判断你猜的数是否正确,如果你猜的数和题目挑的数一样,返回0,如果题目挑的数更小,返回-1,如果题目挑的数更大,返回1。
一开始拿到题目感觉这就是一个二分查找,所以就用二分查找的方法做了,用了递归
public class Solution extends GuessGame {
public int guessNumber(int n) {
return myGuessNumber(1, n);
}
private int myGuessNumber(int begin, int end) {
if (begin == end) {
return begin;
}
int middle = (begin + end) / 2;
int result = guess(middle);
if (result == 0) {
return middle;
} else if (result < 0) {
return myGuessNumber(begin, middle - 1);
} else {
return myGuessNumber(middle + 1, end);
}
}
}
测试了一下没有问题,就提交了,结果报了栈溢出
这下就比较尴尬了,还想着是不是要换方法,但是数据量这么大的话,还是要用二分查找会比较快,要不然可能会超时。想了半天,原来二分查找还可以用循环来实现
public class Solution extends GuessGame {
public int guessNumber(int n) {
return myGuessNumberLoop(1, n);
}
private int myGuessNumberLoop(int begin, int end) {
while (begin < end) {
int middle = (begin + end) / 2;
int result = guess(middle);
if (result == 0) {
return middle;
}
if (result < 0) {
end = middle - 1;
} else {
begin = middle + 1;
}
}
return begin;
}
}
提交后报了另外一个错误,超时
感觉已经没招了,只能去网上搜资源了,这时候看到另外一种写法,尝试了一下,其实只是修改了一行
int middle = (begin + end) / 2;
替换为
int middle = begin + (end - begin) / 2;
然后就过了。。。
只能根据答案猜原因了,这句话是放在循环中执行的,当数据比较大的时候,begin + end 可能会溢出,也有可能是比较大的数的除法比比较小的数的除法要耗时,所以导致上面一种写法会超时但是下面的写法就不会超时。
看了一下网站给出的答案,网站一共给出了三种做法,第一种是直接遍历,肯定超时。第二种是循环的二分查找,第三种是循环的三分查找,这里贴一下代码
public class Solution extends GuessGame {
public int guessNumber(int n) {
int low = 1;
int high = n;
while (low <= high) {
int mid1 = low + (high - low) / 3;
int mid2 = high - (high - low) / 3;
int res1 = guess(mid1);
int res2 = guess(mid2);
if (res1 == 0)
return mid1;
if (res2 == 0)
return mid2;
else if (res1 < 0)
high = mid1 - 1;
else if (res2 > 0)
low = mid2 + 1;
else {
low = mid1 + 1;
high = mid2 - 1;
}
}
return -1;
}
}