C++题解-Leecode 375. 猜数字大小 II——Leecode每日一题系列

Posted 来老铁干了这碗代码

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++题解-Leecode 375. 猜数字大小 II——Leecode每日一题系列相关的知识,希望对你有一定的参考价值。

今天是坚持每日一题打卡的第十七天


题目链接:https://leetcode-cn.com/problems/guess-number-higher-or-lower-ii/submissions/


题解汇总:https://zhanglong.blog.csdn.net/article/details/121071779


题目描述

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

我从 1 到 n 之间选择一个数字。
你来猜我选了哪个数字。
如果你猜到正确的数字,就会 赢得游戏 。
如果你猜错了,那么我会告诉你,我选的数字比你的 更大或者更小 ,并且你需要继续猜数。
每当你猜了数字 x 并且猜错了的时候,你需要支付金额为 x 的现金。如果你花光了钱,就会 输掉游戏 。
给你一个特定的数字 n ,返回能够 确保你获胜 的最小现金数,不管我选择那个数字 。

示例 1:

输入:n = 10
输出:16
解释:制胜策略如下:

  • 数字范围是 [1,10] 。你先猜测数字为 7 。
    • 如果这是我选中的数字,你的总费用为 $0 。否则,你需要支付 $7 。
    • 如果我的数字更大,则下一步需要猜测的数字范围是 [8,10] 。你可以猜测数字为 9 。
      • 如果这是我选中的数字,你的总费用为 $7 。否则,你需要支付 $9 。
      • 如果我的数字更大,那么这个数字一定是 10 。你猜测数字为 10 并赢得游戏,总费用为 $7 + $9 = $16 。
      • 如果我的数字更小,那么这个数字一定是 8 。你猜测数字为 8 并赢得游戏,总费用为 $7 + $9 = $16 。
    • 如果我的数字更小,则下一步需要猜测的数字范围是 [1,6] 。你可以猜测数字为 3 。
      • 如果这是我选中的数字,你的总费用为 $7 。否则,你需要支付 $3 。
      • 如果我的数字更大,则下一步需要猜测的数字范围是 [4,6] 。你可以猜测数字为 5 。
        • 如果这是我选中的数字,你的总费用为 $7 + $3 = $10 。否则,你需要支付 $5 。
        • 如果我的数字更大,那么这个数字一定是 6 。你猜测数字为 6 并赢得游戏,总费用为 $7 + $3 + $5 = $15 。
        • 如果我的数字更小,那么这个数字一定是 4 。你猜测数字为 4 并赢得游戏,总费用为 $7 + $3 + $5 = $15 。
      • 如果我的数字更小,则下一步需要猜测的数字范围是 [1,2] 。你可以猜测数字为 1 。
        • 如果这是我选中的数字,你的总费用为 $7 + $3 = $10 。否则,你需要支付 $1 。
        • 如果我的数字更大,那么这个数字一定是 2 。你猜测数字为 2 并赢得游戏,总费用为 $7 + $3 + $1 = $11 。
          在最糟糕的情况下,你需要支付 $16 。因此,你只需要 $16 就可以确保自己赢得游戏。

示例 2:

输入:n = 1
输出:0
解释:只有一个可能的数字,所以你可以直接猜 1 并赢得游戏,无需支付任何费用。

示例 3:

输入:n = 2
输出:1
解释:有两个可能的数字 1 和 2 。

  • 你可以先猜 1 。
    • 如果这是我选中的数字,你的总费用为 $0 。否则,你需要支付 $1 。
    • 如果我的数字更大,那么这个数字一定是 2 。你猜测数字为 2 并赢得游戏,总费用为 $1 。
      最糟糕的情况下,你需要支付 $1 。

提示:

1 <= n <= 200


思路

题目只给定了一个参数 n,表示在数字 1 到 n 中选择了一个数,我们需要猜中选中的数,而我们每次猜错都要付出一定的代价,代价就是你猜错的那个数,而我们需要求解的就是不管对方选择了什么数,你猜错的最小代价。

一开始,有些同学可能会想到使用二分法来求解,但是,并不可行,使用二分法只能保证你以最少的次数猜中,而不是最小的代价猜中,所以,需要转换思路。

我们可以枚举 1 到 n 中的每一个数,记为 x,分两种情况:

假如 x 正好是选中的数,那么,付出的代价为 0;
假如 x 不是选中的数,那么,付出的代价为 x,然后,我们会得到提示,选中的数比 x 大还是比 x 小:
假如比 x 小,我们只要求得 1 到 x-1 的最小代价,再加上 x 就能得到猜 x 时的最小代价;
假如比 x 大,我们只要求得 x+1 到 n 的最小代价,再加上 x 就能得到猜 x 时的最小代价;
而选中的数有可能在 x 的左边,也可能在 x 的右边,为了保证我们能够赢得游戏,我们需要备用的现金应该是左右两边的最小代价的最大值再加上 x 本身。
当我们枚举完这些 x 后,取其中的最小值就是我们需要备用的现金。

所以,我们可以得到递推公式: f ( 1 ) ( n ) = m i n x = 1 n ( m a x ( f ( 1 ) ( x − 1 ) , f ( x + 1 ) ( n ) ) + x ) f(1)(n) = min_x=1^n(max(f(1)(x-1), f(x+1)(n)) + x) f(1)(n)=minx=1n(max(f(1)(x1),f(x+1)(n))+x)

当然,递推公式中存在若干重复计算, 我们可以设定一个m*n数组,将每次递归得到的结果存入,在计算新值时,如果数组中有此值,直接返回数组值,反之进行递归。


class Solution 
private:
    static const int MAX_SIZE = 200 + 5;
    int memo[MAX_SIZE][MAX_SIZE];
public:
    int getMoneyAmount(int n) 
        return dfs(1, n);
    

    int dfs(int start, int end) 
        if (start >= end) 
            return 0;
        

        if (memo[start][end] != 0) 
            return memo[start][end];
        

        int ans = 0x3fffffff;
        for (int k = start; k <= end; k++) 
            ans = min(ans, max(dfs(start, k - 1), dfs(k + 1, end)) + k);
        

        return memo[start][end] = ans;
    
;

以上是关于C++题解-Leecode 375. 猜数字大小 II——Leecode每日一题系列的主要内容,如果未能解决你的问题,请参考以下文章

LC-375 猜数字大小Ⅱ

375. 猜数字大小 II(区间dp)

18行代码AC-Leecode 299. 猜数字游戏——Leecode每日一题系列

375 Guess Number Higher or Lower II 猜数字大小 II

LeetCode 375 猜数字大小II[动态规划] HERODING的LeetCode之路

LeetCode 495. 提莫攻击 / 629. K个逆序对数组(动规,不会) / 375. 猜数字大小 II(区间dp)