LeetCode-63 不同路径(II)

111 阅读3分钟

一、题目描述

dp1.png

二、题目翻译

还是给定一个网格,在条件AB 的限制下,求出网格起点到终点的路线数量。

条件A:机器人每次只能向下或者向右移动一步。

条件B:网格中增加障碍物,遇到障碍物则不可通过。

备注:网格中的障碍物和空位置分别用 1 和 0 来表示。

输入:二维数组。

三、再来点用例

dp2.png

四、思路讲解

我们可以缩小一下规格,只考虑2*2的网格,如下图:

dp3.png

由上面的图我们可知,从黄球的位置考虑,绿球 -> 黄球 的路径为2条。也就是(1, 0) + (0, 1),但是(0, 1)是障碍物,障碍物是不可通过的,默认是0,所以此时的 绿球 -> 黄球 的公式是下面这样:

绿球到达(1, 0) 的路径数 + 绿球到达(0, 1)的路径数 == 绿球到达(1, 0)的路径数。

根据上面的分析我们可以写出如下代码:

    /**
     * @param {number[][]} obstacleGrid -> 假设此时是2*2的二维网格
     * @return {number}
     */
    var uniquePathsWithObstacles = function(obstacleGrid) {
        let xLength = obstacleGrid.length;        // 有多少个横轴
        let yLength = obstacleGrid[0].length;     // 有多少个纵轴
        let dp = new Array(xLength).fill(new Array(yLength))
        for(let x = 0; x < xLength; x++){
            for (let y = 0; y < yLength; y++){
                if (x > 0 && y > 0){
                    // dp[x][y]:黄球的位置,dp[x-1][y]:障碍物的位置,dp[x][y-1]:(1, 0) 的位置
                    dp[x][y] = dp[x-1][y] + dp[x][y-1];
                }
            }
        }
        return dp[xLength - 1][yLength - 1];
    }

很好,我们现在已经写出来一部分了,但是目前还不能得出来正确的结论,因为我们的二维数组dp里的每一项都没有存储到达这个位置时需要的路径数

如何存储每个单元格需要的路径数?

  • 先判断这个单元格是否是障碍物, 如果是,则为0,如果不是的话,请往下走
  • 如果是第0行上的单元格,那么会有 dp[x][y] = dp[x][y-1]。因为第0行上的单元格,只能通过它左侧的单元格到达
  • 如果是第0列上的单元格,那么会有 dp[x][y] = dp[x-1][y]。因为第0列上的单元格,只能通过它上面的单元格到达
  • 剩余的单元格,那么会有 dp[x][y] = dp[x-1][y] + dp[x][y-1]。这个说的就是黄球。

根据上面的分析,我们来把剩下的代码补全:

    /**
     * @param {number[][]} obstacleGrid -> 假设此时是2*2的二维网格
     * @return {number}
     */
    var uniquePathsWithObstacles = function(obstacleGrid) {
        let xLength = obstacleGrid.length;        // 有多少个横轴
        let yLength = obstacleGrid[0].length;     // 有多少个纵轴
        let dp = new Array(xLength).fill(new Array(yLength));
        // 初始化单元格初始的位置,如果起始位置是障碍物,那就将值置为0,否则就置为1。
        // 初始的位置如果不是障碍物,为什么要置为1?
        // 其实这是从题意分析出来的,因为第0行上的单元格,如果都不是障碍物,
        // 那么到达第0行上的其他单元格的路径数应该是1,
        // 第0行上的单元格的规则:dp[x][y] = dp[x][y-1],
        // 所以最开始的位置如果不是障碍物,就必须置为1。
        dp[0][0] = obstacleGrid[0][0] == 1 ? 0 : 1;
        for(let x = 0; x < xLength; x++){
            for (let y = 0; y < yLength; y++){
                if (obstacleGrid[x][y] == 1){
                    dp[x][y] == 0;
                } else {
                    if (x > 0 && y > 0){
                        // dp[x][y]:黄球的位置,dp[x-1][y]:障碍物的位置,dp[x][y-1]:(1, 0) 的位置
                        dp[x][y] = dp[x-1][y] + dp[x][y-1];
                    } else if (x == 0 && y > 0){
                        dp[x][y] = dp[x][y-1];
                    } else if (y == 0 && x > 0){
                        dp[x][y] = dp[x-1][y];
                    }
                }
            }
        }
        return dp[xLength - 1][yLength - 1];
    }

五、结尾

如果这篇文章能够在思维上帮助你,还请客官不要吝啬手里的小赞赞。我们下篇文章再见喽。