hello 大家好我是django,今天想跟大家分享一下关于动态规划算法的解题思路和方法。其中文章会结合leecode的题目给大家理解
- 在我的理解动态规划说白了就是将上一次的结果缓存起来,在下一次的计算中进行复用。说难也不难说简单也不简单,类似于递归一样也需要采用数学归纳法进行思考(一般会采用一位数组或二维数组进行数据缓存)
动态规划三要素
定义数组元素的含义
例如我们假设数组dp[i]是我们想要求解的值,那么这个数组的含义就被我们定义好了。就是表示第i项时我们需要的答案为dp[i]
找到数组之间的关系
动态规划核心在于是使用之前的缓存值进行下一次计算,所以肯定存在某种关联关系dp[i] = dp[i - 1]...dp[i - 2](往往这一步是最难以想到的)
初始化边界值
就像递归算法一样,在满足某个条件下一定要有返回,否者将会无限调用下去造成死循环,那么动态规划也是一样需要考虑边界问题就例如dp[i] = dp[i - 1]...dp[i - 2]这个表达式当i = 1 or i = 0时是不是就会出现问题了,数组下标将会变成负数。这显然不是我们想要的,所以初始化边界值是动态规划的关键所在。
我们按照上面所说的三要素,来做一做leecode上的题目加深一下三要素的理解
一、青蛙上楼(动态规划)
这道题在leecode上应该是一道简单难度的题目,先给大家小试牛刀找找自信
- 要求
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
- 思路
- 定义
dp[i]为青蛙达到第i层所有的路径(第一要素) - 找到关系
dp[i] = dp[i - 1] + dp[i - 2]确定边界值当i > 2等式成立(第二要素) - 找到初始值,并初始化。当
i <= 2时dp[i] = i(第三要素) 可以看到我们完全符合了动态规划三要素的要求
- 实现
function frogUpstair(n) {
// 定义dp[i]为青蛙到达第i层有dp[i]种方法
// 为什么需要创建n+1个大小的数组?
// 因为需要算第n层 0~n 所以数组大小为 n + 1
const dp = new Array(n + 1).fill(0);
for (let i = 0; i < n; i++) {
if (n <= 2) dp[i] = i;
else {
dp[i] = dp[i - 1] + dp[i - 2];
}
}
return dp[n];
}
很明显这道题其实就是斐波那契数列数列的变种题目,难度稍微比较低
二、不同路径(动态规划)
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
问总共有多少条不同的路径?
示例 1:
输入:m = 3, n = 7
输出:28
示例 2:
输入:m = 3, n = 2
输出:3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右
3. 向下 -> 向右 -> 向下
示例 3:
输入:m = 7, n = 3
输出:28
示例 4:
输入:m = 3, n = 3
输出:6
提示:
1 <= m, n <= 100
题目数据保证答案小于等于 2 * 109
- 思考
- 定义
dp[m][n]为移动到m,n总共有dp[m][n]种方法 - 找到元素关系:当
m >=1, n >= 1时dp[m][n] = dp[m - 1][n] + dp[m][n - 1] - 确认初始值:当
m = 0, n = 0有dp[0][n] = 1, dp[m][0] = 1
- 实现
/**
* @param {number} m
* @param {number} n
* @return {number}
*/
var uniquePaths = function(m, n) {
// 定义 dp[i] 的意义
const dp = new Array(m).fill(0).map(() => new Array(n));
// 找到初始化的值
for(let i = 0; i < m; i++) {
dp[i][0] = 1
}
// 找到初始化的值
for(let i = 0; i < n; i++) {
dp[0][i] = 1
}
for(let i = 1; i < m; i++) {
for(let j = 1; j < n; j++) {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
return dp[m - 1][n - 1];
};
从上面两道题目中我们可以看到,我使用三要素可以比较轻松的找到解题的思路。但是有时候关于元素中的关系是不那么容易找的,但是肯定存在着某种关系。并不是说掌握了三要素对于动态规划就无敌了,算法还是得多刷多练。