版权声明:本文为博主原创文章,转载请注明出处! https://blog.csdn.net/ASN_forever/article/details/85247664
思路:
题目要求的是从左上角即[0,0]位置开始,到右下角即[m-1,n-1]位置为止的最小路径和。倒过来思考的话,对于右下角[m-1,n-1]来说,它的上一步只有两个位置即[m-2,n-1]和[m-1,n-2],因此问题就可以转化为求从[0,0]到这两个位置的路径和的较小值,即状态转移公式为:min ( arr[m-1][n-1] ) = min ( arr[m-1][n-1]+min( arr[m-2][n-1] ),arr[m-1][n-1]+min( arr[m-1][n-2] )),因此可以很容易的用递归方式求解。
解法一:递归法
public int minPathSum(int[][] grid) {
return help1(grid,grid.length-1,grid[0].length-1);
}
public int help1(int[][] arr,int row,int col){
if(row == 0 && col == 0){
return arr[row][col];
}
if(row != 0 && col == 0){
return arr[row][col]+help1(arr,row-1,col);
}
if(row == 0 && col != 0){
return arr[row][col]+help1(arr,row,col-1);
}
return arr[row][col]+Math.min(help1(arr,row-1,col),help1(arr,row,col-1));
}
但是递归法涉及到很多的重复计算,时间复杂度超时,因此需要换一种思路。刚才采用递归法时,考虑的是从后往前求解,那么现在反过来,从前往后可不可以呢?如果能从前往后计算的话,那么就可以依次求出从左上角到任意一个位置的最小路径和了,因为要求的这个位置之前的两个位置的最小值已经知道了,这样就不存在重复计算(即动态规划法)。那么这种思路能不能实现呢?接着思考,对于二维数组来说,在边界上的位置,它的上一步只有一个,而处在中间位置的才有两个。而对二维数组进行遍历的时候,就是从上到下从左到右的遍历的,跟路径的行走规则一致,那么就可以在遍历的时候直接求出每个位置的最小路径和了。
解法二:动态规划法
public int minPathSum(int[][] grid) {
return help(grid);
}
public int help(int[][] arr){
int row = arr.length;
int col = arr[0].length;
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
if(i == 0 && j == 0){
continue;
}
if(i != 0 && j != 0){
arr[i][j] += Math.min(arr[i-1][j], arr[i][j-1]);
}else if(i == 0){
arr[i][j] += arr[i][j-1];
}else{
arr[i][j] += arr[i-1][j];
}
}
}
return arr[row-1][col-1];
}