前言
最近也是在准备蓝桥杯,刷题刷到了动态规划这块,因为之前做题都是一知半解的,所以感觉这块也是比较难的,就下定决心学一下动态规划这块,但是学习过之后才发现,其实思路也是比较简单而且有规律的。下面就举个例子来说明一下动态规划的基本做题思路 。
一、动态规划
简单概念
所谓动态规划就是通过动态填写表格得方式来解决问题。
动态规划主要是需要找出动态转移方程。
可以使用打表分析的方式来进行分析。
题型
- 动态规划基础
- 背包问题
- 打家劫舍
- 股票问题
- 子序列问题
需要弄清楚的概念(动规五部曲):
- dp数组以及下标的含义
- 递推公式
- dp数组初始化
- 遍历顺序
- 打印dp数组
二、简单举例
62. 不同路径
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/unique-paths
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
这道题就是一道简单的动态规划问题,大家可以详细看我下面的代码注释,一共分为四步,但其实是有五步的,最后一步一般是打印dp数组。打印dp数组的话我们一般是在代码逻辑写好之后用来debug检查错误的。
有的人会觉得动态规划中递归公式是关键,其实不然,这五步缺少哪一步都不行,因为基本的动态规划题型就那几种,递推公式也就那几个。
代码
二维数组dp
class Solution {
public int uniquePaths(int m, int n) {
//1.确定dp数组以及下标的含义
//dp[i][j]表示从 0,0出发,到m-1,n-1有dp[i][j]条不同的路径
int[][] dp = new int[m][n];
//2.确定递推公式
//dp[i][j] = dp[i-1][j] + dp[i][j-1];
//3.dp数组的初始化
// 0,0 到 i,0 以及 0,i的路径只有一条,所以
for(int i = 0; i < m; i++) {
dp[i][0] = 1;
}
for(int i = 0 ; i < n;i ++){
dp[0][i] = 1;
}
//4.确定遍历顺序
for(int i = 1;i < m ;i++){
for(int j = 1;j < n;j++){
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
return dp[m-1][n-1];
}
}
一维数组dp优化
一维数组理解上去没有二维数组好理解,所以建议还是熟练使用二维数组后,在尝试一维数组优化
class Solution {
public int uniquePaths(int m, int n) {
//使用一维数组进行优化
//1.确定dp数组以及dp数组下标表示的含义
//dp[i]表示到每层有几条路径
//比如 0,0 -> 0,i
//或者 1,0 -> 1,i
int[] dp = new int[n];
//2.确定递推公式
//dp[i] += dp[i - 1];
//3.初始化dp数组
//将dp数组全部初始化为1
for(int i = 0;i < n; i++){
dp[i] = 1;
}
//4.确定循环遍历顺序
for(int i = 1;i < m ;i++){
for(int j = 1;j < n; j++){
dp[j] += dp[j - 1];
}
}
return dp[n - 1];
}
}