Minimum-Path-Sum——最小路径和
题目描述:
给定一个只含非负整数的m*n网格,找到一条从左上角到右下角的可以使数字和最小的路径。
样例 1:
输入: [[1,3,1],[1,5,1],[4,2,1]]
输出: 7
样例解释:
路线为: 1 -> 3 -> 1 -> 1 -> 1。
样例 2:
输入: [[1,3,2]]
输出: 6
解释:
路线是: 1 -> 3 -> 2
Notice
你在同一时间只能向下或者向右移动一步
AC代码:
1 public class Solution { 2 3 /** 4 * @param grid: a list of lists of integers 5 * @return: An integer, minimizes the sum of all numbers along its path 6 */ 7 public int minPathSum(int[][] grid) { 8 // write your code here 9 if (grid == null || grid.length == 0 || grid[0].length == 0) { 10 return 0; 11 } 12 13 int m = grid.length; 14 int n = grid[0].length; 15 16 // 坐标型动态规划 17 // 最后一步:每个点的路径之和只可能来自上面和左边 18 int[][] dp = new int[2][n]; // 代表(0, 0)到(i, j)的数字和最小的路径 19 20 // 时间复杂度:O(mn) 空间复杂度:O(mn) 21 // 为了降低空间复杂度,这里可以采用滚动数组 22 23 int now = 0, old = 1; 24 int top; 25 int left; 26 // 转移方程 27 for (int i = 0; i < m; i++) { 28 // 这里是滚动数组的最容易忽视的一点:考虑完一行之后才能滚动,不然会出错 29 // 更新 30 old = now; 31 now = 1 - now; 32 for ( int j = 0; j < n; j++) { 33 // 左上角的点 34 if (i == 0 && j == 0) { 35 // 初始化 36 dp[now][0] = grid[0][0]; 37 continue; 38 } 39 dp[now][j] = grid[i][j]; 40 // 判断上面是否有点 41 if (i > 0) { 42 // 上面有点 43 top = dp[old][j]; 44 } else { 45 // 这里设置为无穷大,是为了后面比较,因为是选最小的,反之如果选最大,这里 46 // 可以设置为无穷小 47 top = Integer.MAX_VALUE; 48 } 49 50 // 同理判断左边点是否存在 51 if (j > 0) { 52 left = dp[now][j - 1]; 53 } else { 54 left = Integer.MAX_VALUE; 55 } 56 57 // 比较上面点和左边点的值哪个更小,最后不要忘了加上当前点的值 58 if (top < left) { 59 dp[now][j] += top; 60 } else { 61 dp[now][j] += left; 62 } 63 } 64 } 65 66 return dp[now][n - 1]; 67 } 68 }