62.不同路径

题目链接:62.不同路径

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

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

问总共有多少条不同的路径?

思路

可以建立一个二维dp数组,二维数组中的每个值代表着到达当前下标有多少种不同路径。

首先是初始化,因为机器人只能够向下或向右移动,因此对于所有的i,dp[0][i]都为1,对于所有的j,dp[j][0]也都为1。

然后是遍历顺序,用两层循环来遍历,外层循环是从上到下,内层循环是从左到右进行遍历。

递推式为:dp[i][j] = dp[i - 1][j] + dp[i][j - 1]

以示例1为例子,dp数组如下所示:

正确。

另外,注意到dp数组横向的每一层可以直接取代上一层,而对其他元素没有影响,因此可以被压缩成一维的数组,这时递推式为:dp[j] = dp[j] + dp[j - 1]

初始化时dp[j]均为1。

C++实现

// 原写法
class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>>dp(m, vector<int>(n, 0));
        for(int i = 0;i<m;i++) dp[i][0] = 1;
        for(int j = 0;j<n;j++) dp[0][j] = 1;

        for(int i = 1;i<m;i++){
            for(int j = 1;j<n;j++){
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }
        return dp[m - 1][n - 1];
    }
};

// 将dp数组压缩成一维数组
class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<int> dp(n, 1);
        for(int i = 1;i<m;i++){
            for(int j = 1;j<n;j++){
                dp[j] = dp[j] + dp[j - 1];
            }
        }
        return dp[n - 1];
    }
};

62.不同路径 II

题目链接:62.不同路径 II

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

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

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

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

思路

建立一个二维的dp数组,其中每一个下标代表了到达当前位置有多少条不同的路径。

首先是初始化,对第一层和第一列进行初始赋值。在第一层,从左往右遍历,如果没有遇到石块,当前的dp[0][j] = 1,如果遇到了石块,当前dp[0][j] = 0,并且该层之后的每一项都为0。对第一列的赋值同理。因为机器人只能向下或向右移动,如果在第一层或第一列遇到了石块,那么第一层或第一列的其他位置都到达不了。

然后确定递推式:

如果(i,j)这个位置是石块:dp[i][j] = 0;

否则:dp[i][j] = dp[i - 1][j] + dp[i][j - 1];

遍历顺序同样是两层循环,外层是从上到下,内层是从左往右遍历。

与不同路径类似,这道题的dp数组也可以压缩成一维的,类似于滚动数组。

C++实现

// 原写法
class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int m = obstacleGrid.size(), n = obstacleGrid[0].size();
        vector<vector<int>> dp(m, vector<int>(n, 0));
        for(int i = 0;i<m;i++){
            if(obstacleGrid[i][0] == 1) break;
            else dp[i][0] = 1;
        }
        for(int j = 0;j<n;j++){
            if(obstacleGrid[0][j] == 1) break;
            else dp[0][j] = 1;
        }
        for(int i = 1;i<m;i++){
            for(int j = 1;j<n;j++){
                if(obstacleGrid[i][j] == 1) dp[i][j] = 0;
                else dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }
        return dp[m - 1][n - 1];
    }
};

// 滚动数组
class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int m = obstacleGrid.size(), n = obstacleGrid[0].size();
        vector<int> dp(n, 0);
        for(int j = 0;j<n;j++){
            if(obstacleGrid[0][j] == 1) dp[j] = 0;
            else if(j == 0) dp[j] = 1;
            else dp[j] = dp[j - 1];
        }
        for(int i = 1;i<m;i++){
            for(int j = 0;j<n;j++){
                if(obstacleGrid[i][j] == 1) dp[j] = 0;
                else if(j != 0) dp[j] = dp[j] + dp[j - 1];
            }
        }
        return dp[n - 1];
    }
};
01-20 23:41