给定一个只含非负整数的m*n网格,找到一条从左上角到右下角的可以使数字和最小的路径。
注意事项
你在同一时间只能向下或者向右移动一步
解题思路:
设dp(i,j)为到达该点后的最小路径和。而到达该点一共有两种方法:要么从上边来,要么从左边来,所以写出递推式:
dp(i,j) = grid[i][j] + min(dp(i,j-1) , dp(i-1,j))
递推出口条件为:
起始点:dp(i,j) = grid[i][j]
边界条件:dp(i,0) = grid[i][0] + dp(i-1,j) ; dp(0,j) = grid[0][j] + dp(0,j-1)
再将其改造为循环,即dp(i,j)改为dp[i][j],自底向上循环即可
public class Solution {
/**
* @param grid: a list of lists of integers
* @return: An integer, minimizes the sum of all numbers along its path
*/
public int minPathSum(int[][] grid) {
// write your code here
if(grid==null || grid.length==0 || grid[0].length==0)
return 0;
int m = grid.length;
int n = grid[0].length;
int[][] dp = new int[m][n];
//初始条件与边界条件
dp[0][0] = grid[0][0];
for(int i=1 ; i<m ; i++)
dp[i][0] = grid[i][0] + dp[i-1][0];
for(int j=1 ; j<n ; j++)
dp[0][j] = grid[0][j] + dp[0][j-1];
//递推式
for(int i=1 ; i<m ; i++)
for(int j=1 ; j<n ; j++)
dp[i][j] = grid[i][j] + Math.min(dp[i][j-1], dp[i-1][j]);
return dp[m-1][n-1];
}
}
代码优化:不需要另外新建数组,直接在grid原数组上进行修改。
public class Solution {
/**
* @param grid: a list of lists of integers
* @return: An integer, minimizes the sum of all numbers along its path
*/
public int minPathSum(int[][] grid) {
// write your code here
if(grid==null || grid.length==0 || grid[0].length==0)
return 0;
int m = grid.length;
int n = grid[0].length;
for(int i=0 ; i<m ; i++){
for(int j=0 ; j<n ; j++){
if(i==0 && j==0)
continue;
if(i == 0)
grid[0][j] += grid[0][j-1];
else if(j == 0)
grid[i][0] += grid[i-1][0];
else
grid[i][j] += Math.min(grid[i][j-1], grid[i-1][j]);
}
}
return grid[m-1][n-1];
}
}