题目来源:LeetCode 374:猜数字大小
问题抽象: 设计一个猜数字游戏,目标是通过调用预定义的 guess API 接口,高效找出一个在 [1, n] 范围内的目标整数 target,满足以下核心需求:
-
API 交互规则:
- 预定义函数
guess(int num)返回整型结果:-1:所猜数字num大于target;1:所猜数字num小于target;0:num等于target(成功)。
- 需实现函数
guessNumber(int n),返回目标值target。
- 预定义函数
-
优化目标:
- 最小化 API 调用次数:利用 二分查找 策略(时间复杂度 O(log n));
- 禁止遍历所有数字(避免
O(n)调用)。
-
边界处理:
- 最小范围:
n=1时直接返回1(无需调用 API); - 整数溢出:二分查找中点计算需用
left + (right - left) / 2避免溢出; - 无解情况:输入保证目标值必在
[1, n]内(无需额外检查)。
- 最小范围:
-
计算约束:
- 时间复杂度 O(log n):二分查找最多调用
log₂(n)次guess; - 空间复杂度 O(1):仅需存储左右边界及中点;
- 输入范围:
1 ≤ n ≤ 2^31 - 1(需处理大整数)。
- 时间复杂度 O(log n):二分查找最多调用
输入:整数 n(目标值范围上限)
输出:目标整数 target(1 ≤ target ≤ n)
函数签名:
public class Solution extends GuessGame {
public int guessNumber(int n) {
// 二分查找实现
}
}
预定义接口:
class GuessGame {
int guess(int num) { /* 由系统实现 */ }
}
解题思路
题目要求在 1 到 n 之间猜一个数字,通过调用预定义的 guess 接口获得反馈。解题关键在于高效缩小搜索范围,使用二分查找算法可以将时间复杂度优化至
O
(
log
n
)
O(\log n)
O(logn),空间复杂度为
O
(
1
)
O(1)
O(1)。
算法步骤:
- 初始化边界:左边界
left = 1,右边界right = n。 - 二分查找:
- 计算中间值
mid = left + (right - left) / 2(避免整数溢出)。 - 调用
guess(mid)获取结果:- 若返回
0,直接返回mid(找到目标)。 - 若返回
-1,说明mid偏大,调整右边界right = mid - 1。 - 若返回
1,说明mid偏小,调整左边界left = mid + 1。
- 若返回
- 计算中间值
- 循环终止:当
left <= right时持续搜索(题目保证解存在,无需额外边界判断)。
代码实现(Java版)🔥点击下载源码
public class Solution extends GuessGame {
public int guessNumber(int n) {
int left = 1;
int right = n;
while (left <= right) {
int mid = left + (right - left) / 2; // 防止计算溢出
int res = guess(mid); // 调用预定义API
if (res == 0) {
return mid; // 猜中目标,直接返回
} else if (res == -1) {
right = mid - 1; // 数字过大,缩小右边界
} else {
left = mid + 1; // 数字过小,缩小左边界
}
}
return -1; // 理论不会执行(题目保证解存在)
}
}
代码说明
- 二分查找优化:
- 使用
left + (right - left) / 2计算中间值,避免(left + right)可能导致的整数溢出。 - 每次迭代将搜索范围减半,确保 O ( log n ) O(\log n) O(logn) 时间复杂度。
- 使用
- 边界调整:
guess(mid) = -1:目标小于mid,将右边界设为mid - 1。guess(mid) = 1:目标大于mid,将左边界设为mid + 1。
- 终止条件:
left <= right保证搜索区间有效性,找到目标时立即返回。 - 返回值:循环内必会命中目标(题目数据保证),最后的
return -1仅为语法需要。
提交详情(执行用时、内存消耗)

1万+

被折叠的 条评论
为什么被折叠?



