说明:问题描述来源leetcode
一、问题描述:
64最小路径和
给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
示例 1: 输入:grid = [[1,3,1],[1,5,1],[4,2,1]] 输出:7 解释:因为路径 1→3→1→1→1 的总和最小。
示例 2: 输入:grid = [[1,2,3],[4,5,6]] 输出:12
提示: m == grid.length n == grid[i].length 1 <= m, n <= 200 0 <= grid[i][j] <= 100
二、题解
思路1-回溯(超时)
class Solution {
int target;
int[][] grid;
int row;
int column;
public int minPathSum(int[][] grid) {
target = Integer.MAX_VALUE;
this.grid = grid;
row = grid.length - 1;
column = grid[0].length - 1;
backTracking(0, 0, grid[0][0]);
return target;
}
private void backTracking(int i, int j, int sum) {
if (target < sum) return;//剪枝
if (i == row && j == column) {
target = sum;
return;
}
if (i < row) backTracking(i + 1, j, sum + grid[i + 1][j]);
if (j < column) backTracking(i, j + 1, sum + grid[i][j + 1]);
}
}
先测试:
@Test
public void testSolution(){
int[][][] arr = {
{
{1,3,1},{1,5,1},{4,2,1}//7
},
{
{1,2,3},{4,5,6}//12
},
};
for (int i = 0; i < arr.length; i++) {
System.out.println(Arrays.deepToString(arr[i]) + "`result is " + minPathSum(arr[i]));
}
}
发现在本地测试可以通过。
提交到leetcode平台,结果:60/61,超时,炸裂!
但是起码思路和代码是没错的,本来一眼回溯,果然还是报错了。当时也想到了贪心和dynamic plan,应该是往剩下两个方向走了。
后面把二维数组放局部变量也一样杯水车薪,改变不了超时的结果。
思路2
就来动态规划吧,这个题有类似的题目:[70爬楼梯] (https://blog.csdn.net/ws_please/article/details/129509853)、62不同路径、63不同路径2。
这里得出的规律就是:
第i行第j列的坐标是(i,j),当前坐标数值为grid[i][j],那么到达这个点的最小路径和是min(到达左边最小路径和+当前坐标数值,到达上面最小路径和 + 当前坐标数值)。
题解:
class Solution {
int[][] grid;
public int minPathSum(int[][] grid) {
this.grid = grid;
int row = grid.length;
int column = grid[0].length;
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
if (i == 0 && j == 0) continue;
setMinPathForPoint(i, j);
}
}
return grid[row - 1][column - 1];
}
private void setMinPathForPoint(int i, int j) {
int upSum = Integer.MAX_VALUE;
if (i != 0) upSum = grid[i][j] + grid[i - 1][j];
int leftSum = Integer.MAX_VALUE;
if (j != 0) leftSum = Math.min(upSum, grid[i][j] + grid[i][j - 1]);
grid[i][j] = Math.min(leftSum, upSum);
}
}
后面想了想,这个能不能化成一维数组,这个是可以的,可以化成2个长度为column的一维数组,不过真没必要。因为没必要开辟2个数组,本来就可以利用输入的数组了。