【LeetCode】63. 不同路径 II

问题描述

一个机器人位于一个 m x n 网格的左上角 (起始点在标记为“Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(标记为“Finish”)。

现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?

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

说明:m 和 的值均不超过 100。

示例 1:

输入:
[
  [0,0,0],
  [0,1,0],
  [0,0,0]
]
输出: 2
解释:
3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:
1. 向右 -> 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右 -> 向右

Java 实现

方法一:递归实现

递归实现实际上就是一个动态规划的思想。假设机器人此时正处于位置 (i, j),由于机器人只能向右或者向下走一步,因此在当前位置可以到达终点的路径数,就是向下一步后能到达终点的路径数,与向右一步后能到达终点的路径数,即 dp[i][j] = dp[i+1][j+1]。计算时需要考虑边界条件,而且如果机器人到达了终点,则返回 1 以表示到达此点可算作一个有效路径。

但是,从代码中可以看出,我们每走一步都需要调用一次递归函数,最坏情况可能会调用 m × n 次。

class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        if (obstacleGrid[0][0] == 0) {
            return numOfPath(obstacleGrid, 0, 0);
        } else {
            return 0;
        }
    }

    public int numOfPath(int[][] grid, int i, int j) {
        int m = grid.length, n = grid[0].length;
        
        // Reach the destination.
        if (i == m - 1 && j == n - 1) { 
            return 1;
        }
       
        int cntPath = 0;
        // Go down.
        if (i + 1 < m && grid[i + 1][j] == 0) {
            cntPath +=  numOfPath(grid, i + 1, j);
        }
        // Go right.
        if (j + 1 < n && grid[i][j + 1] == 0) {
            cntPath +=  numOfPath(grid, i, j + 1);
        }
        return cntPath;
    }
}

方法二:动态规划。

思路跟方法一类似,但我们反过来从终点开始计算,构建 dp[][] 矩阵,最后取位置 (0, 0) 的值即为所求。由于当机器人在边缘的时候,它必然只能往一个方向进行下一个。所以,我们可以首先把边缘值计算出来,再把矩阵内部其他值依次填充。

class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int m = obstacleGrid.length, n = obstacleGrid[0].length;    
        
        // Obestacle locates on the start or the destination.
        if (obstacleGrid[0][0] == 1 || obstacleGrid[m-1][n-1] == 1) {
            return 0;
        }

        int[][] dp = new int[m][n];

        // Intialize the number of paths at the edges.
        dp[m-1][n-1] = 1;
        
        // The last column.
        for (int i = m - 2; i >= 0; --i) {
            if (obstacleGrid[i][n-1] == 0) {
                dp[i][n-1] = dp[i+1][n-1];
            }  else {
                dp[i][n-1] = 0;
            } // if
        } // for

        // The last row.
        for (int j = n - 2; j >= 0; --j) {
            if (obstacleGrid[m-1][j] == 0) {
                dp[m-1][j] = dp[m-1][j+1];
            }  else {
                dp[m-1][j] = 0;
            } // if
        } // for

        for (int i = m - 2; i >= 0; --i) {
            for (int j = n - 2; j >= 0; --j) {
                if (obstacleGrid[i][j] == 0) {
                    dp[i][j] = dp[i+1][j] + dp[i][j+1];
                }  else {
                    dp[i][j] = 0;
                } // if
            } // for
        } // for

        return dp[0][0];
    }
}

 

链接:https://leetcode-cn.com/problems/unique-paths-ii/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章