正文
简介【最小路径和】求给定的数组的最小路径和
题目描述#
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
示例:
输入: [ [1,3,1], [1,5,1], [4,2,1] ] 输出: 7 解释: 因为路径 1→3→1→1→1 的总和最小。
我的代码(暴力计算)#
class Solution { volatile int minPath = Integer.MAX_VALUE; public int minPathSum(int[][] grid) { int m = grid.length; int n = grid[0].length; seekTheMinPath(grid, m - 1, n - 1, grid[0][0]); return minPath; } private void seekTheMinPath(int[][] grid, int m, int n, int sum) { if (sum >= minPath) { return; } if (m > 0) { seekTheMinPath(grid, m - 1, n, sum + grid[m][n]); } if (n > 0) { seekTheMinPath(grid, m, n - 1, sum + grid[m][n]); } if (m == 0 && n == 0 && sum < minPath) { minPath = sum; } } }
动态规划的解法#
我们新建一个额外的 dpdp 数组,与原矩阵大小相同。在这个矩阵中,dp(i, j)dp(i,j) 表示从坐标 (i, j)(i,j) 到右下角的最小路径权值。我们初始化右下角的 dpdp 值为对应的原矩阵值,然后去填整个矩阵,对于每个元素考虑移动到右边或者下面,因此获得最小路径和我们有如下递推公式:
dp(i,j)=grid(i,j)+min(dp(i+1,j),dp(i,j+1))
class Solution { public int minPathSum(int[][] grid) { int[][] dp = new int[grid.length][grid[0].length]; for (int i = grid.length - 1; i >= 0; i--) { for (int j = grid[0].length - 1; j >= 0; j--) { if(i == grid.length - 1 && j != grid[0].length - 1) dp[i][j] = grid[i][j] + dp[i][j + 1]; else if(j == grid[0].length - 1 && i != grid.length - 1) dp[i][j] = grid[i][j] + dp[i + 1][j]; else if(j != grid[0].length - 1 && i != grid.length - 1) dp[i][j] = grid[i][j] + Math.min(dp[i + 1][j], dp[i][j + 1]); else dp[i][j] = grid[i][j]; } } return dp[0][0]; } }
复杂度分析#
时间复杂度 :O(mn)O(mn)。遍历整个矩阵恰好一次。
空间复杂度 :O(mn)O(mn)。额外的一个同大小矩阵。