问题:
题目来源:力扣(LeetCode)
难度:中等
分析:
经典的动态规划题。动态规划与递归紧密相连,递归是自顶向下,不断压栈,压到最后一层之后开始向回计算。动态规划是直接从底层向上计算,省去了压栈的空间和重复计算的时间。递归可以用memo优化时间。
动态规划步骤:
第一步,先找状态空间!!这很重要,找到状态空间表示问题所有的状态。
第二步写递推公式!
第三步写base case!
本题递归的思路:
从起点出发,第一步有几种走法?两种:向右和向下。
两种情况是否有重合?无
两种情况是否有遗漏?无
因此总的路径数就是起点右边和下边框出发走过的路径数之和。重复此计算直到到达终点。
本题DP的思路:
递归思路可以直接搬到DP上写,递推公式为dp[i - 1][j - 1] = dp[i] [j - 1] + dp[i - 1][j], base case 是矩阵的最下端一行和最右端一列初始化为1.因为这些格子只有一个方向的走法。
此处为了自底向上思考也可以从终点开始考虑。
到达终点,有几种情况可到达?两种:左边和上边。
两种情况是否有重合?无
两种情况是否有遗漏?无
因此总的路径数就是到达终点左边和终点上边框的路径数之和。从起点开始计算到达每一个点的路径数,直到计算到终点。
递推公式为dp[i][j] = dp[i] [j - 1] + dp[i - 1][j], base case 是矩阵的最上端一行和最左端一列初始化为1.因为这些格子只有一个方向能到达。
优化
时间上无法优化,没有贪心的策略,每一步必须计算到。
空间上可以进一步优化。我们注意到,每一次计算只需要左边和上边的两个值。只要我们保证直到矩阵里的两行数据,计算就可以不断地进行下去。因此O(n*2)可以简化到O(2n)。
进一步地,我们发现在计算的时候,由于我们需要左边和上边的值来更新当前格子,如果用只用一行数据来计算,那么在未更新当前格子值之前,左边格子值是前一步已经更新的值,符合我们的需要;当前格子值是上一行的值,符合我们的需要,所以空间可以简化到O(n)。
解决方法:
1:二维DP
递推公式为dp[i][j] = dp[i] [j - 1] + dp[i - 1][j],ba