leetcode *63. 不同路径 II(滚动数组)

【题目】*63. 不同路径 II

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
在这里插入图片描述
网格中的障碍物和空位置分别用 1 和 0 来表示。
说明:m 和 n 的值均不超过 100。

示例 1:

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

【解题思路1】动态规划

dp数组的状态:dp[i][j] 表示从 (0, 0) 到 (i, j) 的路径总数
边界条件:第0行和第0列分别遍历,赋值为1;如果碰到障碍物,从这个点之后全为0,因为碰到障碍物,之后都不可达了
状态转移条件

  • 当 ob[i][j] == 1 即有障碍,dp[i][j] = 0
  • 当 ob[i][j] == 0 即无障碍,dp[i][j] = dp[i-1][j] + dp[i][j-1]
    因为「机器人每次只能向下或者向右移动一步」,所以 (0, 0) 到 (i, j) 的路径总数的值只取决于 (0, 0)到 (i - 1, j) 的路径总数,加上 (0, 0)到(i, j - 1)的路径总数。
class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int m = obstacleGrid.length;
        int n = obstacleGrid[0].length;
        int[][] dp = new int[m][n];
        for(int i = 0; i < m; i++){
            if(obstacleGrid[i][0] == 0){
                dp[i][0] = 1;
            }else{
                break;
            }
        }
        for(int j = 0; j < n; j++){
            if(obstacleGrid[0][j] == 0){
                dp[0][j] = 1;
            }else{
                break;
            }
        }
        for(int i = 1; i < m; i++){
            for(int j = 1; j < n; j++){
                if(obstacleGrid[i][j] == 0){
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
                }
            }
        }
        return dp[m - 1][n - 1];
    }
}

【解题思路2】滚动数组

滚动数组:当定义的状态在动态规划的转移方程中只和某几个状态相关的时候,就可以考虑这种优化方法,目的是给空间复杂度「降维」。

优化了dp数组空间,因为这里 dp[i][j 仅与 dp[i-1][j] 和 dp[i][j-1] 有关

因为空间压缩后,当前的 f[j] 由 f[j-1] 和 上一轮的 f[j] 转移:f[j-1] 在上一趟循环中已经更新,f[j] 是上一轮的,也已经更新,所以 if (j - 1 >= 0 && obstacleGrid[i][j - 1] == 0) 里的 obstacleGrid[i][j - 1] == 0) 判断可以省略

class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int m = obstacleGrid.length, n = obstacleGrid[0].length;
        int[] f = new int[n];

        f[0] = obstacleGrid[0][0] == 0 ? 1 : 0;
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (obstacleGrid[i][j] == 1) {
                    f[j] = 0;
                }else{
                	//if (j - 1 >= 0 && obstacleGrid[i][j - 1] == 0) 
                    if (j > 0) {
                        f[j] += f[j - 1];
                    }
                }
            }
        }
        return f[n - 1];
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章