一、概念
通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题和最优子结构性质的问题。
二、题型特点
- 计数
- 有多少种方式走到最右下角
- 求最大值最小值
- 从左上角走到右下角的最大数字和
- 求存在性
- 能否选出k个数使得和为sum
三、如何使用动态规划
这里先看一道LeetCode题。从这道题来学习如何使用动态规划。
Coin Change
给定不同面额的硬币 coins 和一个总金额 amount。
编写一个函数来计算可以凑成总金额所需的最少的硬币个数。
如果没有任何一种硬币组合能组成总金额,返回 -1。
示例
输入: coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1
该题是一个求最大最小的动态规划算法题。
与递归解法相比,没有重复计算。
3.1 组成部分一:确定状态
确定状态需要有两个注意的点:最后一步
、子问题
1.最后一步
肯定是(k)枚硬币加起来等于11。最后一枚硬币值假设是(a_k),则剩下的(k-1)枚硬币的值为(11-a_k)。
由于是最优解,则11-(a_k)的硬币数一定是最少。
2.子问题
将原问题转换为子问题,最少用多少枚硬币拼出(11-a_k)
那么(a_k)到底是多少,因为有3枚硬币,所以只可能是1、2、5中的一个。
子问题方程如下:
(f(11) = min{f(11-1)+1,f(11-2)+1,f(11-5)+1})
f(11)为拼出面值为11所需的最少硬币数。
根据以上,使用递归的解法:
public class Dp1 {
public int getMinCoin(int X) {
if (X == 0) return 0;
int res = 10000;
if (X >= 1) {
res = Math.min(getMinCoin(X - 1)+1, res);
}
if (X >= 2) {
res = Math.min(getMinCoin(X - 2)+1, res);
}
if (X >= 5) {
res = Math.min(getMinCoin(X - 5)+1, res);
}
return res;
}
public static void main(String[] args) {
Dp1 dp1 = new Dp1();
int result = dp1.getMinCoin(11);
System.out.println(result);
}
}
使用递归来解决,有比较多的重复计算,效率比较低。
动态规划会保存计算结果,来避免递归重复计算的问题。
3.2 组成部分二:转移方程
动态规划的解法
状态f[X]表示,面值为X所需的最小硬币数。
对于任意的X,满足
(f[X] = min{f[X-1]+1,f[X-2]+1,f[X-5]+1})
意思就是获取面值大小为X最少需要的硬币数 = 从(最后一个硬币选1时,剩下的要凑面值为X-1所需要的最少硬币数,因为最后一个硬币选了1,所以硬币数要+1,即f[x-1]+1)、(f[X-2]+1)、(f[X-5]+1)中选择一个最少的硬币数。
3.3 组成部分三:初始条件和边界情况
设置初始值,考虑边界情况。
3.4 组成部分四:计算顺序**
从上到下,从左到右。
四、LeetCode题完整解法
class Solution {
public int coinChange(int[] coins, int amount) {
int[] f = new int[amount+1];
int coin_num = coins.length;
//初始条件
f[0] = 0;
//f[x] = min{f[x-c1]+1,f[x-c2]+1,f[x-c3]+1}
for(int x = 1;x<=amount;x++){
f[x] = Integer.MAX_VALUE;
for(int i = 0;i<coin_num;i++){
// 考虑输入[2],4,则需要保证f[x-coins[i]] != Integer.MAX_VALUE,即f[x-coins[i]]必须要是存在的状态
if(x >=coins[i] && f[x-coins[i]] != Integer.MAX_VALUE){
f[x] = Math.min(f[x-coins[i]]+1,f[x]);
}
}
}
// 考虑输入[2],3,则amount = -1
if(f[amount] == Integer.MAX_VALUE){
return -1;
}
return f[amount];
}
}
参考文档
参考视频
动态规划入门 Introduction to Dynamic Programming
ACM专题讲解:DP动态规划
算法数据结构面试通关(经验全集)