到底怎么学动态规划?
回想起当初学动态规划的时候,是真的难。动态规划的确很难,很考验逻辑思惟能力、抽象能力、还有数学建模能力。 可是入门动态规划真的有这么难吗?我觉的其实真的不难,就是单纯的找规律;这里我想以一种比较野路子的方式帮助你们入门理解动态规划,这种方法真的是很简单且有效果,大神请忽略。markdown
DP table
什么方法呢?直接画表格,找规律。 这个办法在不少题目下都是很是的有效果,特别是矩阵型dp,简直是万金油;这种方法很是简单,你只须要记住两个技巧。spa
- 把问题的规模变小,变成小问题思考
- 根据小问题来填表格,找出规律
记住这两个技巧,下面我以一道相对简单,一道稍微难一点的真题还讲解。code
62.不一样路径
首先分析一下题目,题目说机器人只能往下,或者往右走,到达右下角有多少种走法。
- 不要单纯的干想,单纯的干想会浪费不少的时间,甚至手足无措,彻底不知道怎么办了,直接画表格找规律,这里我以一个5*7的表格来举例。
- 首先为何第一行第一列全是1?由于若是只有第一行第一列,机器人就只有一条路可走。
- 回忆一下上面两个技巧;假设咱们把网格变小,也就是把问题的规模变小,变成一个3*3的表格。
- 3*3 有多少种走法很简单吧?直接把表格填完就能够获得答案了,答案就是6种。
- 为何是6种呢?由于机器人只能往右或者往下走,到达3 * 3的最右下角,只能往上面下来,或者左边过来。
- 那若是把问题的规模继续变大,变成4*4的表格呢?咱们继续填表
- 继续观察答案,答案是20种;那有什么规律呢?我相信没有人会发现不了这个规律吧?
- 很明显,table[3][3] = table[2][3] + table[3][2],也就是说机器人走到规模为4 * 4的网格右下角有20种走法。
书写代码
到这里,我相信写出代码应该不难了吧?orm
var uniquePaths = function (m, n) {
// 由于第一行第一列都是1
let dp = Array.from(new Array(m), () => new Array(n).fill(1))
for(let i = 1; i < m; i++){
for(let j = 1; j < n; j++){
// 当前的等于上面的(dp[i - 1][j])+ 左边的(dp[i][j - 1])
dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
}
}
return dp[m - 1][n - 1]
};
复制代码
其实动态规划也就这么简单,就是单纯的画表格找规律。数学
1143.最长公共子序列
- 分析下题目,要找两个串的最长公共子序列,不要多想。直接画表格观察规律
- 为何会有空串?为何空串对应的都是0?你想呀,须要从无到有推导出答案,找出规律,因此须要借助空串;若是两个串中的其中一个为空,那确定都是0呀。
- 由于用例的答案是3,全部我先把结果先上去,好利用这个结果来找出规律。
- 咱们继续填表推导,找出规律。
- 当问题的规模变大,text1[0] == text2[0],答案很明显是1。这里咱们就发现了相等的时候要加1了,好家伙,继续观察。
- 为何我会先填 text1[0] == text2[0] 对应的行和列呢?由于当text1/text2的长度继续变长的时候,最终的结果会受影响吗?很明显,不受影响,继续填表找规律。
- 当咱们填到text1[i] == text2[j],也就是c字符相等的时候,由以前找到的规律,它必定要加1,可是在哪一个基础上加1呢?很明显是问题的规模变小的时候,也就是没有c这个字符的时候,也就是表格的table[1][2],绿色区域为1的块。
- 继续以这个规律填表格看看,咱们看红色块。
- 最终验证了答案,当两个字符相等的时候,就等于上一个规模小的问题加1,不想等的就至关于有没有这个字符都同样。取两个串少一个的状况下的最大值就能够了。
- 因此规律以下:
- text1[i] == text2[j], table[i][j] = table[i - 1][j - 1] + 1
- text1[i] != text2[j], table[i][j] = max(table[i - 1][j], table[i][j - 1])
书写代码
var longestCommonSubsequence = function(text1, text2) {
let n = text1.length
let m = text2.length
let dp = Array.from(Array(n + 1), () => Array(m + 1).fill(0))
//空串都是0,0不用看了
for(let i = 1; i <= n; i++){
for(let j = 1; j <= m; j++){
if(text2[j - 1] == text1[i - 1]){
dp[i][j] = dp[i - 1][j - 1] + 1
}else{
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1])
}
}
}
return dp[n][m]
};
复制代码
总结
其实这种办法写动态规划是很是野路子的,可是对于新手来讲,入门确实不错。 动态规划确实有点难,把它讲明白,讲清楚也不简单,但愿我这篇水文能帮助你更好的理解动态规划吧。互联网人共勉~it