数据结构与算法之查找: Leetcode 374. 猜数字大小 (Typescript版)

猜数字大小

  • https://leetcode.cn/problems/guess-number-higher-or-lower/

描述

  • 猜数字游戏的规则如下:
    • 每轮游戏,我都会从 1 到 n 随机选择一个数字。 请你猜选出的是哪个数字。
    • 如果你猜错了,我会告诉你,你猜测的数字比我选出的数字是大了还是小了。
  • 你可以通过调用一个预先定义好的接口 int guess(int num) 来获取猜测结果,返回值一共有 3 种可能的情况(-1,1 或 0):
    • -1:我选出的数字比你猜的数字小 pick < num
    • 1:我选出的数字比你猜的数字大 pick > num
    • 0:我选出的数字和你猜的数字一样。恭喜!你猜对了!pick == num
  • 返回我选出的数字。

示例 1

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

示例 2

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

示例 3

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

示例 4

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

提示

  • 1 <= n <= 2 31 2^{31} 231 - 1
  • 1 <= pick <= n

算法实现

1 )迭代 + 二分实现

/** 
 * Forward declaration of guess API.
 * @param {number} num   your guess
 * @return 	     -1 if num is higher than the picked number
 *			      1 if num is lower than the picked number
 *               otherwise return 0
 * var guess = function(num) {}
 */

function guessNumber(n: number): number {
    let low: number = 1;
    let high: number = n;

    while(low <= high) {
        let mid = Math.floor((low + high) / 2);
        let res = guess(mid); // 这个guess 由系统实现,不用管
        // 猜对了
        if (res === 0) return mid;
        // 猜小了
        if (res === 1) low = mid + 1;
        // 猜大了
        if (res === -1) high = mid - 1;
    }
}
  • 解题思路
    • 二分查找
    • 迭代对比
    • 调用guess函数,判断中间元素是否是目标值
  • 解题步骤
    • 从数组的中间元素开始,如果中间元素正好是目标值,则查找过程结束
    • 如果目标值大于或小于中间元素,则在数组大于或小于中间元素那一半中查找
  • 时间复杂度:O(logn)
    • 二分查找
  • 空间复杂度:O(1)
    • 没有线性增长的内存
  • 这种算法比下面的递归算法要好

2 )递归 + 二分实现

/** 
 * Forward declaration of guess API.
 * @param {number} num   your guess
 * @return 	     -1 if num is higher than the picked number
 *			      1 if num is lower than the picked number
 *               otherwise return 0
 * var guess = function(num) {}
 */

function guessNumber(n: number): number {
    // 递归函数
    const rec = (low: number, high: number) => {
        if(low > high) return;
        const mid = Math.floor((low + high) / 2);
        const res = guess(mid);
        // 猜对了
        if(res === 0) return mid;
        // 猜小了
        if(res === 1) return rec(mid + 1, high);
        // 猜大了
        return rec(1, mid - 1);
    }
    return rec(1, n);
}
  • 解题思路
    • 二分查找,减而治之
  • 解题步骤
    • 计算中间元素,分割数据,基于中间值进行guess操作,得到中间值的结果, 基于中间值缩小数据规模
    • 递归地在较大或较小子数组进行二分搜索
  • 时间复杂度:O(logn)
  • 空间复杂度:O(n)
    • 用了递归,调用堆栈
    • 栈内变量没有被释放
    • 内存存储是线性增长的
    • 具体空间用了多少要看递归堆栈有多少层
    • 遇到一分为二的不停分割问题,是log(n)
  • 推荐用上面while循环版而非递归版

你可能感兴趣的:(Data,Structure,and,Algorithms,leetcode,算法,查找)