LeetCode之 动态规划总结

动态规划

  • 什么情况下可以用到动态规划问题(求所有,不用)
    1、求最大值/最小值(从左上角到右上角路径的最大数字和、最长上升子序列长度)
    2、求方案数(有多少种方式走到右下角、有多少种方法选出K个数使得和是Sum)
    3、求存在性(取石子游戏,先手是否必胜;能不能选出K个数使得和是Sum)

  • 动态规划四步解题法
    1、确定状态
    2、状态方程
    3、初始条件和边界情况
    4、计算顺序

  • 举例说明解法
    你有三种硬币,分别面值2元,5元和7元,每种硬币都有足够多。买一本书需要27元。如何用最少的硬币组合正好付清,不需要对方找钱?
    确定状态:
    1、先看最后一步
    最后一步:存在最后一枚硬币,an(2、5、7)
    不去关心前面的a1、a2…an-1,只确定前面拼出了27-an
    2、分解为子问题
    如果an是2,f(27)应该是:f(27-2)+1
    如果an是5,f(27)应该是:f(27-5)+1
    如果an是7,f(27)应该是:f(27-7)+1
    状态方程:
    对于任意x:f[x]=min{ f[x-2]+1,f[x-5]+1,f[x-7]+1}
    初始条件和边界情况:
    初始条件:设定f(0)=0
    边界情况:如果不能组合出Y,设定f(Y)=正无穷
    dp[i]=Integer.MAX_VALUE;
    if (i-coins[j]>=0&&//钱数大于硬币数值
    dp[i-coins[j]]!=Integer.MAX_VALUE&&//之前子问题没有最优解
    dp[i-coins[j]]+1<dp[i])//下一个金额硬币数量大于上一个
    举例:1、f(1)=f(1-2)+1=f(-1)+1=正无穷 2、 f(2)=f(2-2)+1=f(0)+1=1
    计算顺序:
    可能要考虑,从f(27)、f(26)还是f(1)、f(2)开始呢?
    原则:f(x)=f(x-1)+f(x-2)+…确保,等式右边都是已知的,计算过的。如果计算f(5)的时候,发现f(3)还没有计算,那就是错的。

for (int i = 1; i <dp.length; i++) {
    for (int j = 0; j < n; j++) {
    ....
    }
}

原题:

public static void main(String[] args) {
        int[] coins=new int[]{2,5,7};
        System.out.println(coinChange(coins,59));
    }
    public static int coinChange(int[] coins,int amount){
        //硬币的数量
        int n=coins.length;
        //换取i元的最小硬币数量
        int[] dp=new int[amount+1];
        //初始条件
        dp[0]=0;
        //状态方程
        for (int i = 1; i <dp.length; i++) {
            dp[i]=Integer.MAX_VALUE;
            for (int j = 0; j < n; j++) {
                //边界条件
                if (i-coins[j]>=0&&//钱数大于硬币数值
                dp[i-coins[j]]!=Integer.MAX_VALUE&&//之前子问题没有最优解
                dp[i-coins[j]]+1<dp[i])//下一个金额硬币数量大于上一个
                    dp[i]=dp[i-coins[j]]+1;
            }
        }
        if (dp[amount]==Integer.MAX_VALUE)
            return -1;
        else
            return dp[amount];
    }

运行结果:
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值