小菜找实习-动态规划

前言:最近做了一些国内大厂的笔试,发现国内大厂很喜欢考动态规划。这篇文章记录一下自己对动态规划的学习。

计划在26号之前练习二十道左右的DP题,题的来源选择leetcode吧,难度主要在在medium和hard之间。

针对几个比较经典的题目,会写具体的文章去分析。

动态规划一般解决什么问题

1.计数

  • 有多少种方式走到右下角
  • 有多少种方法选出k个数使得和是sum

2.求最大最小值

  • 从左上角走到右下角路径的最大数字和
  • 最长上升子序列长度

3.求存在性

  • 取石子(取书)游戏,先手是否必胜
  • 能不能选出k个数使得和是Sum

我们先以coin change这个题目来举例分析动态规划的一般解题思路

动态规划组成部分一:确定状态

  • 状态是定海神针
  • 简单的说,解决动态规划的时候一般需要开一个数组,数组的每个元素F[i]或者F[i][j]代表什么
  • 确定状态需要两个意识

1.最后一步

 

     2.子问题

动态规划组成部分二:转移方程

  • 设状态F[x] = 最少用多少枚硬币拼出x
  • 对任意x,F[x] = min{F[x-2]+1,F[x-5]+1,F[x-7]+1}

动态规划组成部分三:初始条件和边界条件

  • x-2,x-5或者x-7小于0怎么办?什么时候停下?
  • 如果拼不出Y,怎么定义F[Y],(可以考虑定义为F[Y]=amount+1) 最后如果F[x]=amount+1说明拼不出来
  • 还有比如F(1)=min{F[-1]+1,F[-4]+1,F[-6]+1},此时是因为1块钱太少,没法用拼出来。说明我们在每一步dp前要判断进入状态转移的条件是否满足,不满足就不进行状态转移的操作。
  • 初始条件F[0]=0

 

动态规划组成部分四:计算顺序

  • 每一步尝试三种硬币,一种27步
  • 与递归算法相比,没有任何重复计算
  • 算法时间复杂度:27*3 如果要拼成的金额为n,有m种硬币,那么时间复杂度为m*n

coin change(leetcode300)代码如下

class Solution {
    public int coinChange(int[] coins, int amount) {
        //corner case 
        if(coins==null||coins.length==0)return 0;
        int []dp = new int[amount+1];
        Arrays.fill(dp,amount+1);
        dp[0]=0;
        for(int i=1;i<=amount;i++){
            for(int j=0;j<coins.length;j++){
                if(i-coins[j]>=0){
                dp[i]=Math.min(dp[i],dp[i-coins[j]]+1);
            }
            }
        }
        
        return dp[amount]==amount+1? -1:dp[amount];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值