话不多说,题目描述如下:
最近在做数组和字符串的题目的时候,我发现很多都是动态规划的问题啊也就是DP(dynamic programming),我就发现这种动态规划的思想我掌握的不行啊,我这暴脾气我非要把动态规划给搞定啊!然后看了很多篇博客。对动态规划有了一定的了解,然后我们一起分析一下这道题。
其实动态规划和递归有些像,刚开始接触的时候很容易弄混,也有很多博主总结对比了递归,备忘录递归然后和动态规划做对比。
那我们看这道题,比如方格是m×n的,在到达右下角之前的一步,是不是我们只有两种选择,那就是我们在(m-1,n-2)或者(m-2,n-1),到这可以稍微停10秒,想想是不是这么回事。既然这样。那我们是不是可以类比于递归的思想,只不过递归是自上而下的运算,小伙伴们可以用递归敲一下斐波那契问题,然后再用备忘录递归方法敲一下,其实就是把计算结果保存在一个二维数组里面而已,省去了我们在普通的递归计算中那些因为重复计算而导致的时间复杂度高带来的问题。相信敲完代码印象就会更深刻,那递归呢?递归恰恰相反,但首先也是把每次都计算结果保存到数组中,然后自底向上计算,但是我们还应该考虑一下临界条件,就是第一行和第一列的位置。是不是只有一种走法呢?因为每次只能向下或者向右走。所以第一行和第一列的值要初始化为一。下面我们看代码
int[][] f = new int[m][n];
for (int i = 0; i < m; ++i) {
f[i][0] = 1;
}
for (int j = 0; j < n; ++j) {
f[0][j] = 1;
}
for (int i = 1; i < m; ++i) {
for (int j = 1; j < n; ++j) {
f[i][j] = f[i - 1][j] + f[i][j - 1];
}
}
return f[m - 1][n - 1];
其实代码很简单,关键是那个状态转移方程,也就是我们最开始会想到用递归的那个方程,然后我们想到用二维数组来记录我们已经计算过的结果,避免重复计算。然后我们又自底向上计算,并且初始化第一列和第一行为1。之后才是动态当成,到当前位置的路径和等于到(m-1,n-2)和(m-2,n-1)这两个位置的路径数量之和每一个位置某如此,所以最后会计算出到右下角的路径之和。
至此我们就彻底的搞懂了这道题,由于写完这篇文章的时候已经快12点了,脑袋有点反应慢哈哈以上内容有哪些说错或者没有表达清楚的地方,希望大家在评论区指正~