63. Unique Paths II

最后更新

四刷?

依然是尝试用一维DP。

每次更新DP的时候相当于直接添加了2个方向的贡献值。

开始的dp[1] = 1不好理解,其实是代表每行第一个格子dp[j]来自左边的贡献值,来自上面的贡献值是他本身,我们在上一行算过,所以是dp[j] + 1。

下个格子dp[j+1]就变成了来自左边的贡献值 —— dp[j](刚刚算的) + 来自上面的贡献值 dp[j+1], 所以是dp[j+1] + dp[j]。。

如果是障碍物直接是0,没啥可说的。

Time: O(mn)
Space: O(min(m,n))

public class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        if (obstacleGrid.length == 0) return 0;

        
        int row = obstacleGrid.length;
        int col = obstacleGrid[0].length;
        
        int[] dp = new int[col + 1];
        dp[1] = 1;
        
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (obstacleGrid[i][j] == 1) {
                    dp[j+1] = 0;
                } else {
                    dp[j+1] += dp[j];
                }
            }
        }
        
        return dp[col];
    }
}


一刷

小机器人走路的变体,典型DP。

现在加了个条件,有障碍,那无非是有障碍的那格是0.

public class Solution 
{
    public int uniquePathsWithObstacles(int[][] grid) 
    {
        if(grid.length == 0) return 0;
        
        int[][] dp = new int[grid.length][grid[0].length];
        dp[0][0] = grid[0][0] == 1? 0:1;
        
        if(dp[0][0] == 0)
            return 0;
        
        for(int i = 1; i < dp[0].length;i++)
        {
            if(grid[0][i] == 1) dp[0][i] = 0;
            else dp[0][i] = dp[0][i-1];
        }
        for(int i = 1; i < dp.length;i++)
        {
            dp[i][0] = grid[i][0] == 1? 0:dp[i-1][0];
        }
        
        
        for(int i = 1; i < dp.length;i++)
            for(int j = 1; j < dp[0].length;j++)
            {
                dp[i][j] = grid[i][j] == 1? 0:(dp[i-1][j] + dp[i][j-1]);
            }
        return dp[grid.length-1][grid[0].length-1];
        
    }
}

Extra Space是n²,实际上不用,只需要2列,或者2行就行了。

dp[i][j]是从当前列+前一列 得出来的,所以只记录这俩就够了。

但是具体怎么实现没写代码,三刷再说吧。。


三刷。

二维DP记录就不说了。说说如何把m * n空间变成 M..

到dp[m][n]的解来自于dp[m-1][n]和dp[m][n-1]

遍历的时候是一行一行(一列一列)遍历的。

dp[1][1]来自于dp[1][0]
dp[2][1]来自于dp[2][0]
dp[3][1]来自于dp[3][0]
..这是每个点更新时来自于横向或者纵向其中一个方向的贡献,然后还有另一个方向。
问题是终归他们是相加的,不如先横向都加了,再总向把所有的和加起来。

另一个地方是初始化,如果是0的话,需要判断一下最外层;这里手动添加了半圈,结果不影响。

Time: O(nm)
Space: O(n)

public class Solution {
    public int uniquePathsWithObstacles(int[][] grid) {
        if (grid.length == 0) return 0;
        
        int[] dp = new int[grid[0].length + 1];
        dp[1] = 1;
        for (int i = 1; i <= grid.length; i++) {
            for (int j = 1; j <= grid[0].length; j++) {
                if (grid[i-1][j-1] == 0) {
                    dp[j] += dp[j - 1];
                } else {
                    dp[j] = 0;
                }
            }
        }
        
        return dp[grid[0].length];
    }
}
原文地址:https://www.cnblogs.com/reboot329/p/6128000.html