【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/

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