Leetcode.374 猜数字大小
题目描述
猜数字游戏的规则如下:
- 每轮游戏,我都会从 1 到 n 随机选择一个数字。 请你猜选出的是哪个数字。
- 如果你猜错了,我会告诉你,你猜测的数字比我选出的数字是大了还是小了。
你可以通过调用一个预先定义好的接口 int guess(int num)
来获取猜测结果,返回值一共有 3 种可能的情况(-1
,1
或0
):
-1
:我选出的数字比你猜的数字小pick < num
1
:我选出的数字比你猜的数字大pick > num
0
:我选出的数字和你猜的数字一样。恭喜!你猜对了!pick == num
返回我选出的数字。
数据范围 :
1 < = n < = 2 31 − 1 1 <= n <= 2^{31} - 1 1<=n<=231−1
示例1
输入: n = 10,pick = 6
输出: 6
后续示例不用再看了,pick是几输出就是几。
解题思路1 暴力枚举 O ( n ) O(n) O(n)
从1开始往后走,直到找到那个数为止,最长是从1到n遍历一遍,因此复杂度为
O
(
n
)
O(n)
O(n),但是本题的数据范围是大于int
的,因此这么做会超时。所以该解法不可取。
解题思路2 二分 O ( l o g n ) O(logn) O(logn)
我们容易想到我们平常玩这种游戏时是先说出中间那个数,然后看看是大了还是小了,如果当前猜的数mid
大于答案pick
,那么我们再从1
到mid
中取出中间的数进行判断。
这个算法中,每次判断都会去掉当前数字中一半的数字,因此假设需要进行判断的次数为k
,那么
2
k
=
n
2^k = n
2k=n,
k
=
l
o
g
2
n
k = log_{2}{n}
k=log2n,所以用二分做这题的时间复杂度为
O
(
l
o
g
n
)
O(logn)
O(logn)。
代码
/**
* Forward declaration of guess API.
* @param num your guess
* @return -1 if num is lower than the guess number
* 1 if num is higher than the guess number
* otherwise return 0
* int guess(int num);
*/
class Solution {
public:
int guessNumber(int n) {
long long l = 1,r = n;
while(l < r){
long long mid = l + r>> 1;
if(guess(mid) == 0) return mid;
else if(guess(mid) == 1) l = mid + 1;
else r = mid;
}
return l;
}
};