Easy

题目描述

我们正在玩一个猜数字游戏,游戏规则如下:

我从 1 到 n 之间选择一个数字。你来猜我选的是哪个数字(我选的数字在整个游戏过程中保持不变)。

每当你猜错时,我会告诉你你猜的数字比我选的数字是大了还是小了。

你可以通过调用一个预先定义的接口 int guess(int num) 来获取猜测结果,返回值一共有 3 种可能的情况(-1,1 或 0):

  • -1:你猜的数字比我选的数字大 (即 num > pick)
  • 1:你猜的数字比我选的数字小 (即 num < pick)
  • 0:你猜的数字和我选的数字一样 (即 num == pick)

返回我选的数字。

示例 1:

输入:n = 10, pick = 6
输出:6

示例 2:

输入:n = 1, pick = 1
输出:1

示例 3:

输入:n = 2, pick = 1
输出:1

提示:

  • 1 <= n <= 2^31 - 1
  • 1 <= pick <= n

解题思路

这是一道经典的二分查找问题。我们需要在 1 到 n 的范围内找到目标数字。

解题思路:

由于题目提供了 guess() API,可以告诉我们当前猜测的数字与目标数字的大小关系,这为二分查找提供了完美的条件。

  1. 初始化边界:设置左边界 left = 1,右边界 right = n

  2. 二分搜索过程

    • 计算中点 mid = left + (right - left) / 2,避免整数溢出
    • 调用 guess(mid) 获取结果
    • 根据返回值调整搜索范围:
      • 返回 -1:说明 mid 太大,目标在左半部分,更新 right = mid - 1
      • 返回 1:说明 mid 太小,目标在右半部分,更新 left = mid + 1
      • 返回 0:找到目标,直接返回 mid
  3. 时间复杂度优化:每次查找都能排除一半的搜索空间,效率很高

这种方法保证了在最坏情况下也只需要 O(log n) 次猜测就能找到答案。

代码实现

class Solution {
public:
    int guessNumber(int n) {
        int left = 1, right = n;
        
        while (left <= right) {
            int mid = left + (right - left) / 2;
            int result = guess(mid);
            
            if (result == 0) {
                return mid;
            } else if (result == -1) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        
        return -1;
    }
};
class Solution:
    def guessNumber(self, n: int) -> int:
        left, right = 1, n
        
        while left <= right:
            mid = left + (right - left) // 2
            result = guess(mid)
            
            if result == 0:
                return mid
            elif result == -1:
                right = mid - 1
            else:
                left = mid + 1
        
        return -1
public class Solution : GuessGame {
    public int GuessNumber(int n) {
        int left = 1, right = n;
        
        while (left <= right) {
            int mid = left + (right - left) / 2;
            int result = guess(mid);
            
            if (result == 0) {
                return mid;
            } else if (result == -1) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        
        return -1;
    }
}
var guessNumber = function(n) {
    let left = 1;
    let right = n;
    
    while (left <= right) {
        let mid = Math.floor((left + right) / 2);
        let result = guess(mid);
        
        if (result === 0) {
            return mid;
        } else if (result === 1) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
};

复杂度分析

复杂度类型复杂度说明
时间复杂度O(log n)二分查找,每次排除一半搜索空间
空间复杂度O(1)只使用常数级别的额外空间

相关题目