最小路径和
给定一个包含非负整数的 m x n
的网格 grid
,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
1 | 输入:grid = [[1,3,1],[1,5,1],[4,2,1]] |
示例 2:
1 | 输入:grid = [[1,2,3],[4,5,6]] |
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 200
0 <= grid[i][j] <= 100
分析:一般来说,遇到这种统计可行路径的数量,或者求最小路径的时候,使用动态规划和搜索这两种方法,但是搜索更适用于数据规模较小的题目
动态规划
动态规划算法,我们主要关注以下两点。
状态的设置。在这个题目里,由于要求最小路径和,我们可以令 dp[ i ] [ j ] 代表从(i,j)点走到右下角点的最小路径和。
状态转移方程。我们考虑如何来求出 dp [ i] [j]。由于每次只能往右或者下走,所以从(i,j)只能走到(i+1,j)或者(i,j+1)。换言之,dp[ i ] [ j ] 的前继状态只有dp[ i+1 ] [ j ], dp[ i ] [ j+1 ], 所以我们在两者取最小,然后加上这个格子内的数即可
dp(i,j) = grid(i,j) + min(dp(i + 1,j),dp(i,j + 1))
是需要特殊处理的,当然还有终点元素也是要做个排除,下面先看流程图
就以案例一的矩阵为例子:
1 | 输入:grid = [[1,3,1],[1,5,1],[4,2,1]] |
逆向思维
从终点考虑问题,思考上一点在哪
最后一列是只能向上回
最后一行是只能向左回
终点不做处理
上代码:
1 | class Solution { |
正向思维
即从起点出发,思考下一点在哪
只有第一行是可以向右
只有第一列是可以向下
起点不做处理
上代码:
1 | public class Solution { |
优化(状态压缩)
这是官方的优化说明:
1 | 我们可以用一个一维数组dp来代替二维数组,dp 数组的大小和grid的列大小相同。 |
这是我个人的解读(对于逆向思维)
1 | 想要得到最后的结果,就需要从第一行开始计算,然后该行的数据为下一行的计算提供数据。 |
这里就不画流程图了,直接上代码
1 | class Solution { |