给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。
(1)动态规划
1,要明白上边界线的点只能由它的上一个点向右移动所得,而左边界线的点只能从由它的上一个点向下移动所得;
2,从左上角grid[0][0]到右下角grid[row-1][col-1],遍历整个数组grid,然后记录当前位置grid[i][j]上面所需步数的最小值,一直到遍历完成;
3,最后拿到的就是grid[row-1][col-1]就是所需的答案;
class Solution {
public int minPathSum(int[][] grid) {
return dynamic(grid,row-1,col-1);
}
//使用动态规划,只能向下或者向右移动,当前位置记录每次经过这个位置路径上时的最小值(遍历一遍)
private int dynamic(int[][] grid) {
//先去取得行列的长度
int row = grid.length;
int col = grid[0].length;
for (int i = 0; i < row; i ++) {
for (int j = 0; j < col; j ++) {
//起始点(原点)直接跳过
if (i == 0 && j==0)
continue;
//上边界,只能由向右移动所得
else if (i == 0)
grid[i][j] += grid[0][j-1];
//左边界只能时向下所得
else if (j == 0)
grid[i][j] += grid[i-1][0];
//中间位置,记录经过时的最小值
else
grid[i][j] += Math.min(grid[i-1][j], grid[i][j-1]);//向右向下所得都有可能;
}
}
return grid[row-1][col-1];
}
注意:从grid[0][0]开始遍历,对边界线和其他情况分开判断;问题分解,不断取得当前的最优解,然后得到下一个最优解,直到完成整个过程;
(2)递归法,
1,从数组的终点开始递归,拿到所有可能的情况,最后取得里面的最小路径;
2,对边界线进行特殊处理;
3,递归到原点则结束;
class Solution {
public int minPathSum(int[][] grid) {
int row = grid.length;
int col = grid[0].length;
return dynamic(grid,row-1,col-1);
}
//递归(会超时)
private int dynamic(int[][] grid, int row, int col) {
//停止的条件
if (row == 0 && col == 0)
return grid[row][col];
//左边界
if (row != 0 && col == 0)
return grid[row][col] + dynamic(grid, row-1,0);
//上边界只能向右所得
if (row == 0 && col != 0)
return grid[row][col] + dynamic(grid, 0, col-1);
//中间情况,等于两边相加(取小值)
return grid[row][col] + Math.min(dynamic(grid,row-1,col), dynamic(grid, row, col-1));
}
}
注意:递归法由于要拿到所有可能,计算庞大,会超时的哦。