代码随想录算法训练营第三十九天|LeetCode62. 不同路径、LeetCode63. 不同路径 II

一、LeetCode62. 不同路径

题目链接:62. 不同路径
这道题我们要用一个m* n的二维数组dp来存储走到每一个网格时的所有路径。
因为题目要求从左上角每次只能往下或往右走一步,最后走到右下角结束。
所以每处于一个网格中时我们只可以选择往右或者往下走一步(前提是不超出网格范围)。
然后我们可以用一个先进先出的队列来存放每一个步长所能到达的所有网格,同时删掉前一步到达的网格。
注意因为每个网格(起始位置除外)只能从它上一格向下走一步或者左一格向右走一步到达,所以到达每个网格的路径总数是上一格的路径数加上左一格的路径数。
当然我们首先需要初始化起始位置的路径数为一,即dp[0][0] = 1。
代码如下:

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int> >dp(m, vector<int>(n, 0));//用一个二维数组存放到达每一个网格的路径数
        dp[0][0] = 1;//初始化第一个网格,路径数为1
        queue<pair<int, int> > que;//用一个队列存放每走一步所能到达的所有坐标
        que.push(pair(0, 0));
        int p, q;
        while(que.size() != 0) {//队列长度不为0说明,还可以走下一步
            p = que.front().first;
            q = que.front().second;
            que.pop();//记录队头的坐标,然后删除队头
            //cout<<p << " " << q <<" "<< dp[p][q] <<endl;
            //向下走一步或者向又走一步
            if(q + 1 < n) {
                if(dp[p][q + 1] == 0) {//如果右边的dp坐标值为0,说明该坐标还没走过,将它放到队列中
                    que.push(pair(p, q + 1));
                }
                //因为每一个网格都只能从它上一格向下走一步或者左一格向右走一步到达
                //所以走到每一个网格的路径为它上面一格的路径加上左边一格的路径
                dp[p][q + 1] += dp[p][q];
            }
            if(p + 1 < m) {
                if(dp[p + 1][q] == 0) {
                    que.push(pair(p + 1, q));
                }
                dp[p + 1][q] += dp[p][q];
            }
            
        }
        return dp[m - 1][n - 1];

    }
};

二、LeetCode63. 不同路径 II

题目链接:63. 不同路径 II
这道题解法跟上一道类似,只不过多了一个对障碍物的判断。
我们在向右或者向下走一步时需要判断一下是否有障碍物,如果有就不能走。
只要掌握了上一道的解法这道题其实就很简单了!
代码如下:

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        if(obstacleGrid[0][0] == 1) return 0;//如果起始位置有障碍物则无法到达任何一个地方
        //记录以下网格的长宽
        int m = obstacleGrid.size();
        int n = obstacleGrid[0].size();
        vector<vector<int> >dp(m, vector<int>(n, 0));//用一个二维数组存储到达每一个网格的路径数
        int p, q;
        queue<pair<int, int> > que;
        dp[0][0] = 1;
        que.push(pair(0, 0));
        while(que.size() != 0) {
            p = que.front().first;
            q = que.front().second;
            que.pop();
            //向右或向下走一步,判断是否有障碍物
            if(q + 1 < n && obstacleGrid[p][ q + 1] == 0) {
                if(dp[p][q + 1] ==0) {
                    que.push(pair(p, q + 1));
                }
                dp[p][q + 1] += dp[p][q];
            }
            if(p + 1 < m && obstacleGrid[p + 1][q] == 0) {
                if(dp[p + 1][q] == 0) {
                    que.push(pair(p + 1, q));
                }
                dp[p + 1][q] += dp[p][q];
            }
        }
        return dp[m - 1][n - 1];

    }
};

总结

总以为动态规划会很难,没想到只要掌握了卡哥的动态规划五步曲还是可以自己解决很多题目的!
动态规划五部曲:
1、确定dp数组(dp table)以及下标的含义。
2、确定递推公式
3、dp数组的初始化
4、确定遍历顺序
5、举例推导dp数组

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值