JAVA(2021-11-12)leetcode每日一题----猜数字大小 II

JAVA(2021-11-12)leetcode每日一题----猜数字大小 II_第1张图片

这个题个人感觉有点难,想了半天,还看了题解才写出来

首先这个题要用动态规划而不是二分,二分根本做不下去。

为了将支付的金额最小化,除了需要将每次支付的金额控制在较低值以外,还需要在猜数字的过程中缩小所选数字的范围。当猜了数字 xx 并且猜错时,会知道 xx 比所选数字大还是小。如果 xx 比所选数字大,则任何比 xx 大的数字一定都比所选数字大,因此应该在比 xx 小的数字中继续猜数字。如果 xx 比所选数字小,同理可知应该在比 xx 大的数字中继续猜数字。

我们定义二位数组dp[ i ][ j ],用于表示 i - j 内确保胜利的最少金额,目标是计算 dp(1, n),所以根据上述的条件,我们可以得到dp的推导式

dp[i][j] = k + Math.max(dp[i][k-1],dp[k+1][j])

接下来我们要开始dp,首先我们要对dp数组进行初始化,并且确定dp的方向,观察我们的表达式,如果我们的i从小到大开始遍历,我们要知道dp[k+1][j]的值,k+1大于i,我们不知道这个值是多少,所以i要从大到小遍历,因为k-1必然小于j,所以j要从小到大开始遍历,这样一来,我们思路就清晰了。

min = Math.min(val, min);

这个部分,为啥是min,就是说我要从我所有的策略中,找到花费最小的那个策略,比如3-4中猜数,如果我猜3,如果结果是4,那么h我会花费3块钱,但是如果我猜4,如果结果是3,我就会花费4块钱,花3块钱和4块钱都可以得到正确的结果,我肯定要花费少的那个。

 int val = k + Math.max(dp[i][k - 1], dp[k + 1][j]);
                    //找出其中花费的最小值

这个部分,为什么我要找最大值,比如4,5,6,7四个数,我的需求是我的钱要恰好完成这个游戏,我不能玩到一半钱不够我玩了,比如我猜6,答案就是6,那我不用花钱我就猜对了,我就带0块钱就行了,但是如果答案是4,我猜6,我猜错了,我需要支付6块钱,我再猜5,我又错了,直到猜对之前我要支付11块钱,但是我只带了0块钱,我无法玩这种情况的游戏,所以我要找到这个游戏的所有情况的钱,而不是最好情况的钱。

综上所述,我要满足游戏中所有情况,但是我又要猜的好,即最大值中取最小值

class Solution {
    public int getMoneyAmount(int n) {
        int[][] dp = new int[n + 1][n + 1];
        //从大到小遍历i
        for (int i = n - 1; i >= 1; i--) {
            //从小到大遍历j
            for (int j = i + 1; j <= n; j++) {
                //我要找到[i,j]中所花费的最小值
                int min = Integer.MAX_VALUE;
                for (int k = i; k < j; k++) {
                    //val的值代表我猜k的时候,所花费的钱,因为要满足所有的条件,所以要取最大值
                    int val = k + Math.max(dp[i][k - 1], dp[k + 1][j]);
                    //找出其中花费的最小值
                    min = Math.min(val, min);
                }
                dp[i][j] = min;
            }
        }
        return dp[1][n];
    }
}

你可能感兴趣的:(leetcode,leetcode,java,动态规划)