题目:
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
示例:
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小
思路:和63,62题的思路一致,都是使用动态规划的思想。参考网上大神的代码,还有一种将存储空间变为一个一维数组的。思路是一样的。
使用动态规划的思想,并且用一个一位数组表示dp[i]表示一行中到达di个格子目前最短的路径。
我自己写了一个最基本的代码,就是代码1.但是在写代码的时候总是忘了考虑到特殊的情况,就是最上边的一行和最左边的那一列。
代码:
代码1:
class Solution {
public int minPathSum(int[][] grid) {
int rows = grid.length;
int cols = grid[0].length;
int[][] dp = new int[rows][cols]; //用来记录当前节点到左上角的最短路径
dp[0][0]= grid[0][0];
for(int i=0;i<rows;i++){
for(int j=0;j<cols;j++){
if(i==0&&j==0)continue;
else if(i==0&&j!=0){
dp[i][j]=dp[i][j-1]+grid[i][j]; //对第一行的处理
}
else if(i!=0&&j==0){
dp[i][j]=dp[i-1][j]+grid[i][j]; //对第一列的特殊处理
}
else
dp[i][j]=Math.min(dp[i-1][j], dp[i][j-1])+grid[i][j]; //对于普通位置,等于本身的值加上上面或者左边之间的最小值
}
}
return dp[rows-1][cols-1];
}
}
代码2:
public static int shortestRoad1(int arr[][]) {
int dp[]=new int[arr[0].length];
dp[0]=arr[0][0];
for(int j=1;j<arr[0].length;j++) {
dp[j]=dp[j-1]+arr[0][j]; //求出第一行的dp
}
for(int i=1;i<arr.length;i++) {
dp[0]=arr[i][0]+dp[0]; //dp[0]代表每一行最左边的dp,
//后一行的dp覆盖前一行的dp
for(int j=1;j<arr[0].length;j++) {
dp[j]=Math.min(dp[j-1]+arr[i][j], dp[j]+arr[i][j]);
}
}
return dp[arr[0].length-1];
}
执行最快的代码:
使用了递归的思想。好像有点像深度优先搜索的感觉。超出边界返回最大值;到达终点(右下角的位置);之前已经计算过该值(算是被标记过)。这三种情况返回,剩下的请求继续递归。类似于图的那种,从起点开始找。
我自己试着写了下这个代码,发现好多问题。比如说有几个变量是private的,还有就是私有函数中各种情况的返回值有些不懂。
我自己写的时候把最重要的递归那部分写错了。。。。
class Solution {
private int[][] grid;
private int sum;
private int[][] temp;
public int minPathSum(int[][] grid) {
this.grid=grid;
temp=new int[grid.length][grid[0].length] ;
int x=0;
int y=0;
return minPath(0,0);
}
private int minPath(int x,int y){
if(x==grid.length-1&&y==grid[0].length-1){
return grid[x][y];
}
if(x>grid.length-1||y>grid[0].length-1){
return Integer.MAX_VALUE;
}
if(temp[x][y]!=0){
return temp[x][y];
}
temp[x][y]=grid[x][y]+Math.min(minPath(x+1,y),minPath(x,y+1));
return temp[x][y];
}
}