力扣63. 不同路径 II

题目来源(力扣):

https://leetcode.cn/problems/unique-paths-ii/description/

题目描述:

一个机器人位于一个 m x n 网格的左上角 。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角。
其中有些网格有障碍物,不可以经过。
问总共有多少条不同的路径?

基本思路:

力扣62. 不同路径 几乎相同 https://leetcode.cn/problems/unique-paths/description/
只是多了障碍物,特殊处理即可。
数组定义、遍历顺序都不变,只是在初始化和dp数组求解过程中,对于障碍物进行了处理。

初始化步骤中,如果第0行的某个位置有障碍物,则该位置及其之后的位置都不可到达;第0列同理。
dp数组求解过程中,如果位置(i,j)是障碍物,则直接跳过该位置(并且dp[i][j]=0)即可

代码实现:

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int m = obstacleGrid.size(), n = obstacleGrid[0].size();
        // 1.定义dp数组
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));

        // 2.确定递推方程
        // dp[i][j]=dp[i-1][j]+dp[i][j-1];

        // 3.初始化
        for (int i = 0; i < m; i++) { // 初始化第一列
            if (obstacleGrid[i][0])
                break; // 遇见障碍物,则之后的所有的位置都不可以到达
            dp[i][0] = 1;
        }
        for (int j = 0; j < n; j++) { // 初始化第一行
            if (obstacleGrid[0][j])
                break; // 遇见障碍物,则之后所有的位置都不可以到达
            dp[0][j] = 1;
        }

        // 4.确定递推顺序 左上到右下
        // 左上到右下,但是优先行
        //  for(int i=1;i<m;i++){
        //      for(int j=1;j<n;j++){
        //          if(obstacleGrid[i][j]){
        //              //dp[i][j]=0;//这句可以不写,因为默认为0
        //              continue;
        //          }
        //          dp[i][j]=dp[i-1][j]+dp[i][j-1];
        //      }
        //  }

        // 左上到右下,但是优先列
        for (int j = 1; j < n; j++) {
            for (int i = 1; i < m; i++) {
                if (obstacleGrid[i][j]) {
                    // dp[i][j]=0;//这句可以不写,因为默认为0
                    continue;
                }
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }

        // 5.打印(部分)dp数组以确定是否符合预期
        //  for(int i=0;i<m;i++){
        //      for(int j=0;j<n;j++)
        //          cout<<dp[i][j]<<" ";
        //      cout<<endl;
        //  }

        return dp[m - 1][n - 1];
    }
};

时间复杂度

O(m*n)

补充

力扣62. 不同路径相似,此题dp数组依旧可以压缩为1维的。

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int m = obstacleGrid.size(), n = obstacleGrid[0].size();
        // 1.定义dp数组
        vector<int> dp(n + 1);

        // 2.确定递推方程
        // dp[j]=dp[j]+dp[j-1];

        // 3.初始化
        for (int j = 0; j < n; j++) { // 初始化第一行
            if (obstacleGrid[0][j])
                break; // 遇见障碍物,则之后所有的位置都不可以到达
            dp[j] = 1;
        }

        // 4.确定递推顺序 左上到右下
        // 左上到右下,优先行
        for (int i = 1; i < m; i++) {
            if (obstacleGrid[i][0])
                dp[0] = 0; // 每行第一个位置特殊判定一下
            for (int j = 1; j < n; j++) {
                if (obstacleGrid[i][j]) {
                    dp[j] = 0;  //此时不能省略,因为二位dp数组有默认值0,而1维dp数组需要手动维护
                    continue;
                }
                dp[j] = dp[j] + dp[j - 1];
                // cout<<dp[j]<<" "; //5.打印(部分)dp数组以确定是否符合预期
            }
            // cout<<endl;
        }

        return dp[n - 1];
    }
};
posted @ 2024-12-02 13:29  HB_Computer  阅读(36)  评论(0)    收藏  举报