leetcode 猜数字大小 II

题目链接
区间动态规划

思路:动态规划
分析:如果n等于1,那么明显,不需要花费现金
如果n等于2,那么花费现金最小是1
如果n等于3,那么花费现金是2
.。。。。
n,如果我们猜x,如果对了,显然就没了,但是如果小了,那么也就是需要在x+1,到n中继续猜测,如果大了,那么也就是继续在1,x-1中猜,那么我们可以定义一个dp[i][j]表示在i到j中猜中所需要的最少的现金。
i==j的时候,也就是只有一个数,那么显然不用花费现金
i>j的时候,此时不存在,也就是不用猜,那么也就不用花费现金
所以i<j
并且dp[i][j]初始化为 j+dp[i][j-1]
那么在i到j的中间,我们猜测一个x,也就是说 i<x<j,那么三种情况,
第一:x正好中了,也就是dp[i][j]不变;
第二:x大了,也就是dp[i][j] = x+dp[i][x-1]
第三:x小了,也就是dp[i][j] = x+dp[x+1][j]
这三种情况都可能出现,但是要保证现金一定够可以猜中的,那么dp[i][j]等于上面二三种情况中最大的与自身比最小的那个

而且,可以看出,这里的dp[i][j]可以划分为更小的子问题,也就是可以划分为 i — x-1 x+1 ------ j的问题。
那么我们需要保证i—x-1 x+1-----j 是已经得出了结果的,那么我们需要i从大到小移动,j从i+1到n移动。
代码:

class Solution {
    public int getMoneyAmount(int n) {
        int[][] dp = new int[n+1][n+1];

        //i是从大到小   j是从i+1到n
        for(int i = n-1;i>=1;i--){
            
            for(int j = i+1;j<=n;j++){
                //j猜错了,j大了,这里的j 是  i+1~n,前面的是算好了的
                //这里是为了当k=j的时候,k+1有越界的问题,所以提前算好一下
                dp[i][j] = j + dp[i][j-1];
                for(int k = i ; k<j ; k++){
                    //所有的最大的代价中最小的
                    dp[i][j] = Math.min(dp[i][j],k+Math.max(dp[i][k-1],dp[k+1][j]));
                }
            }
        }
        return dp[1][n];
    }
}

思路二:动态规划,以长度为最外层循环
这个动态规划代码更好理解一些。
代码:

class Solution {
    public int getMoneyAmount(int n) {
        int[][] dp = new int[n+1][n+1];

        //区间长度
        for(int len = 2 ; len<=n ; len++){

            //起始点
            for(int start = 1; start + len -1 <=n;start++){

                //结束点
                int end = start + len - 1;
                
                //初始化dp[start][end],选取区间的第一个,并且是猜错的情况,此时肯定是猜小了
                dp[start][end] = start + dp[start+1][end];

                //从start+1开始遍历
                for(int k = start+1 ; k < end; k++){
                    //当前猜错的情况,并且需要花费的最大的金额
                    int cur = k + Math.max(dp[start][k-1],dp[k+1][end]);
                    //选择最大金额的最小值
                    dp[start][end] = Math.min(dp[start][end], cur);
                }
            }
        }
        return dp[1][n];
    }
}

好好学习。
不打扰是我的温柔。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值