动态规划
根据九章算法视频做的笔记
链接:https://www.bilibili.com/video/BV1xb411e7ww
动态规划题目特点
- 计数
- 求最值
- 求存在性
解题步骤
- 确定状态
最后一步和子问题 - 转移方程
- 初始条件和边界情况
- 计算顺序
做题
1. LeetCode322. 零钱兑换
给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。
计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。
你可以认为每种硬币的数量是无限的。
链接:https://leetcode-cn.com/problems/coin-change
- 求最值型动态规划
class Solution {
public int coinChange(int[] coins, int amount) {
// 总额为 0 的情况直接返回 0
if (amount == 0) {
return 0;
}
// 最少次数的数组
int[] minCount = new int[amount + 1];
minCount[0] = 0;
int MAX_VALUE = Integer.MAX_VALUE;
for (int i = 1; i < minCount.length; i++) {
int minValue = MAX_VALUE;
for (int j = 0; j < coins.length; j++) {
if (i - coins[j] < 0) {
continue;
}
minValue = Math.min(minCount[i - coins[j]], minValue);
}
// 防止越界
minCount[i] = minValue == MAX_VALUE ? minValue : minValue + 1;
}
return minCount[amount] < MAX_VALUE ? minCount[amount] : -1;
}
}
2. LeetCode62. 不同路径
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
问总共有多少条不同的路径?
链接:https://leetcode-cn.com/problems/unique-paths
- 计数型动态规划
class Solution {
public int uniquePaths(int m, int n) {
int[][] a = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
// 左边第一列和上方第一排为 1
if (i == 0 || j == 0) {
a[i][j] = 1;
continue;
}
a[i][j] = a[i-1][j] + a[i][j-1];
}
}
return a[m - 1][n - 1];
}
}
注意:m == 1 && n == 1
时我以为结果为 0
,但是结果是 1
。
另解法(组合数学):
机器人一定会走 m+n-2
步,即从 m+n-2
中挑出 m-1
步向下走或者从 m+n-2
中挑出 n-1
步向右走的次数。
即
C
m
+
n
−
2
m
i
n
(
m
−
1
,
n
−
1
)
C^{min(m-1,n-1)}_{m+n-2}
Cm+n−2min(m−1,n−1) 种走法
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
return comb(m + n - 2, min(n - 1, m - 1))