题目
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
示例
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。
思路一(超时)
找到所有的路径,计算路劲和,取最小。
代码一
class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
int temp = 0;
int minSum = INT_MAX;
dfs( grid, 0, 0, temp, minSum );
return minSum;
}
void dfs( vector<vector<int>>& grid, int row, int col, int temp, int& minSum ) {
if ( row == grid.size() || col == grid[0].size() )
return;
if ( row == grid.size() - 1 && col == grid[0].size() - 1 ) {
temp += grid[row][col];
minSum = min( temp, minSum );
return;
}
dfs( grid, row+1, col, temp+grid[row][col], minSum );
dfs( grid, row, col+1, temp+grid[row][col], minSum );
return;
}
};
思路二
- 对于一个格子,要么是上面的格子向下走一步,要么是左边的格子向右走一步。所以当计算当前格子为终点的最小路径和值时,只需要选择上左两个格子中较小的值,再加上自己的值,即为当前格子最小的路劲和。
- 对于第一行的格子,因为路径只有从左向右一条,所以每个格子逐加自身值。
- 对于第一列的格子,路径只有从上到下一条,所以逐加。
- 从第二行第二列开始按行遍历,计算以每个格子为终点的最小的路径和。
代码
class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
if ( grid.size() == 0 ) return 0;
int m = grid.size();
int n = grid[0].size();
for ( int i = 1; i < m; ++i )
grid[i][0] += grid[i-1][0];
for ( int j = 1; j < n; ++j )
grid[0][j] += grid[0][j-1];
for ( int i = 1; i < m; ++i ) {
for ( int j = 1; j < n; ++j ) {
grid[i][j] += min( grid[i-1][j], grid[i][j-1] );
}
}
return grid[m-1][n-1];
}
};