参考资料

动态规划其实很简单

动态规划

动态规划入门

理解动态规划

左神 DP 思路

1.分析可变参数的范围,构造表格

2.标出计算的终止位置

3.标出不要计算直接出答案的位置 base case

4.推普遍位置如何依赖其他位置的

5.定出严格表依次计算的顺序

斐波那契数列

509. 斐波那契数

问题

斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 01 开始,后面的每一项数字都是前面两项数字的和。也就是:

1
2
F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1

给定 n ,请计算 F(n)

动态规划

确定dp数组以及下标含义

dp[i]:第i个数的斐波那契数值为dp[i]

确定dp递推公式

初始化dp数组

1
2
dp[0] = 0;
dp[1] = 1;

确定dp数组遍历顺序

根据 dp 公式, dp[i]是依赖 dp[i - 1]dp[i - 2],那么遍历的顺序一定是从前到后遍历

举例推导dp数组

1
[0 1 1 2 3 5 8 13 21 34 55]

原始版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public int fib(int N) {
if (N <= 1) {
return N;
}
// 定义dp数组
int[] dp = new int[N + 1];
// 初始化dp数组
dp[0] = 0;
dp[1] = 1;
for (int i = 2; i <= N; ++i) {
dp[i] = dp[i -1] + dp[i - 2];
}
// 返回计算终止位置
return dp[N];
}

空间压缩版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public int fib(int N) {
if (N <= 1) {
return N;
}
// 定义dp数组
int[] dp = new int[2];
// 初始化dp数组
dp[0] = 0;
dp[1] = 1;
for (int i = 2; i <= N; ++i) {
int sum = dp[0] + dp[1];
dp[0] = dp[1];
dp[1] = sum;
}
// 返回计算终止位置
return dp[1];
}

矩阵快速幂

矩阵乘法

1
2
3
4
5
6
7
8
9
10
11
public int[][] muliMatrix(int[][] matrix1, int[][] matrix2) {
int[][] ans = new int[matrix1.length][matrix2[0].length];
for (int i = 0; i < matrix1.length; i++) {
for (int j = 0; j < matrix2[0].length; j++) {
for (int k = 0; k < matrix2.length; k++) {
ans[i][j] += matrix1[i][k] * matrix2[k][j];
}
}
}
return ans;
}

矩阵快速幂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public int[][] matrixPower(int[][] matrix, int p) {
int[][] ans = new int[matrix.length][matrix[0].length];
// 先把ans设为单位矩阵
for (int i = 0; i < ans.length; i++) {
ans[i][i] = 1;
}
int[][] temp = matrix;
while (p > 0) {
// 二进制位中不为0的部分
if ((p & 1) != 0) {
ans = muliMatrix(ans, temp);
}
p >>= 1;
temp = muliMatrix(temp, temp);
}
return ans;
}

fib

1
2
3
4
5
6
7
8
9
10
11
public int fib(int n) {
if (n < 1) {
return 0;
}
if (n == 1 || n == 2) {
return 1;
}
int[][] base = {{1, 1}, {1, 0}};
int[][] res = matrixPower(base, n - 2);
return res[0][0] + res[1][0];
}

不同路径

62. 不同路径

问题

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。

问总共有多少条不同的路径?

暴力递归

记忆化搜索

滚动数组优化

最小路径和

64. 最小路径和

三角形最小路径和

120. 三角形最小路径和

动态规划基础

零钱兑换

322. 零钱兑换

最长连续递增子序列

674. 最长连续递增序列

完全平方数

279. 完全平方数

跳跃游戏

55. 跳跃游戏

解码方法

91. 解码方法

不同路径Ⅱ

63. 不同路径 II

滚动数组优化技巧

动态规划强化

回文串专题

最长回文子串

5. 最长回文子串

最少分割回文串

132. 分割回文串 II

经典双串专题

最长公共子序列

LCR 095. 最长公共子序列

编辑距离

72. 编辑距离

正则表达式匹配

10. 正则表达式匹配

乘积最大的子数组

152. 乘积最大子数组

股票专题

买卖股票的最佳时机

121. 买卖股票的最佳时机

买卖股票的最佳时机 Ⅱ

122. 买卖股票的最佳时机 II

买卖股票的最佳时机 Ⅲ

123. 买卖股票的最佳时机 III

打家劫舍

198. 打家劫舍