64. Minimum Path Sum

题目描述

给定一个只含非负整数的 m x n 网格,找到一条从左上角到右下角的可以使数字之和最小的路径。

注意: 每次只能向下或者向右移动一步。

示例 1:

[[1,3,1],
 [1,5,1],
 [4,2,1]]

根据上面的数组,返回 7. 因为路径 1→3→1→1→1 总和最小。

我的解法——DP(AC)

  • 每个格子可能从上面、左面走下来。
  • 注意:初始边界情况
  • 复杂度O(n2)
  • 结果:Beat47.37%
class Solution:
    def uniquePathsWithObstacles(self, obstacleGrid):
        """
        :type obstacleGrid: List[List[int]]
        :rtype: int
        """
        m = len(obstacleGrid)
        n = len(obstacleGrid[0]) if(len(obstacleGrid) != 0) else 0
        dp = [[0 for j in range(n)] for i in range(m)]  # 注意:初始要设置为0,不是-1了
        if(obstacleGrid[0][0] == 0):
            dp[0][0] = 1

        for i in range(m):
            for j in range(n):
                if(obstacleGrid[i][j] == 0):
                    dp[i][j] += dp[i - 1][j] if(i - 1 >= 0 and obstacleGrid[i - 1][j] == 0) else 0
                    dp[i][j] += dp[i][j - 1] if(j - 1 >= 0 and obstacleGrid[i][j - 1] == 0) else 0
        return dp[m - 1][n - 1]

最优解法——改进DP

  • 利用grid数组,空间轮转
  • sum[j] = min(sum[j],sum[j-1]) + grid[i]/[j]
  • 空间复杂度为0
public class Solution {
    public int minPathSum(int[][] grid) {
        int m = grid.length;// row
        int n = grid[0].length; // column
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (i == 0 && j != 0) {
                    grid[i][j] = grid[i][j] + grid[i][j - 1];
                } else if (i != 0 && j == 0) {
                    grid[i][j] = grid[i][j] + grid[i - 1][j];
                } else if (i == 0 && j == 0) {
                    grid[i][j] = grid[i][j];
                } else {
                    grid[i][j] = Math.min(grid[i][j - 1], grid[i - 1][j])
                            + grid[i][j];
                }
            }
        }

        return grid[m - 1][n - 1];
    }
}