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

LeetCode 62 不同路径

题目链接:https://leetcode.cn/problems/unique-paths/

思路:

使用动态规划五部曲:

  1. 使用一个二维数组dp[i][j],代表第(i,j)位置上有多少个路径

  1. 确定递推公式:

想要求dp[i][j],只能有两个方向来推导出来,即dp[i - 1][j] 和 dp[i][j - 1]。

此时在回顾一下 dp[i - 1][j] 表示啥,是从(0, 0)的位置到(i - 1, j)有几条路径,dp[i][j - 1]同理。

那么很自然,dp[i][j] = dp[i - 1][j] + dp[i][j - 1],因为dp[i][j]只有这两个方向过来。

  1. 递归数组初始化

显然,第一行和第一列的每个位置都只有一条路径能到达,所以:

for (int i = 0; i < m; i++) dp[i][0] = 1;
for (int j = 0; j < n; j++) dp[0][j] = 1
  1. 确定遍历顺序

因为后面的值要用到前面的值,所以显然是从前往后遍历

代码:

class Solution {
public:
    int uniquePaths(int m, int n) {
        if(m==1&n==1)   return 1;
         vector<vector<int>>dp(m,vector<int>(n));
         for(int i = 1;i<n;i++)
            dp[0][i] = 1;

        for(int i = 1;i<m;i++)
            dp[i][0] = 1;

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

总结

使用动规五部曲,轻松解决。要注意边界条件。

LeetCode 63 不同路径 II

题目链接:https://leetcode.cn/problems/unique-paths-ii/

思路:

思路和62.不同路径相类似,只是此时有了障碍就需要注意,如果障碍在第一行或者第一列中,初始化dp数组时,出现障碍的位置之后都为0.

代码:

  • 自写

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int m = obstacleGrid.size();
        int n = obstacleGrid[0].size();
        vector<vector<int>>dp(m,vector<int>(n,0));

        if(obstacleGrid[0][0]==1)   return 0;
        if(m==1&&n==1&&obstacleGrid[0][0]==0)  return 1;

        for(int i = 1;i<n;i++)
        {
            if(obstacleGrid[0][i]==1)
            {
                while(i<n)
                {
                    dp[0][i] = 0;
                    i++;
                }
                break;
            }
            else
                dp[0][i] = 1;
        }

        for(int i = 1;i<m;i++)
        {
            if(obstacleGrid[i][0]==1)
            {
                while(i<m)
                {
                    dp[i][0] = 0;
                    i++;
                }
                break;
            }
            else
                dp[i][0] = 1;
        }

        for(int i = 1;i<m;i++)
        {
            for(int j = 1;j<n;j++)
            {
                if(obstacleGrid[i][j]==1)
                    continue;
                else
                    dp[i][j] = dp[i][j-1]+dp[i-1][j];
            }
        }

        // for(int i = 0;i<dp.size();i++)
        // {
        //     for(int j = 0;j<dp[0].size();j++)
        //         cout<<dp[i][j]<<" ";
        //     cout<<endl;
        // }
        // cout<<endl;

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


};
  • 卡哥代码

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int m = obstacleGrid.size();
        int n = obstacleGrid[0].size();
    //如果在起点或终点出现了障碍,直接返回0
    if (obstacleGrid[m - 1][n - 1] == 1 || obstacleGrid[0][0] == 1) 
            return 0;
        vector<vector<int>> dp(m, vector<int>(n, 0));
        // 如果在第一行或者第一列出现了障碍那么就让后面的数保持为0
        for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++) dp[i][0] = 1;
        for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++) dp[0][j] = 1;
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                if (obstacleGrid[i][j] == 1) continue;
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }
        return dp[m - 1][n - 1];
    }
};

总结

想法和代码都可以写出来,但是自己写的代码非常的冗杂。需要学习卡哥写的代码。

今日总结:

动规五部曲的应用,相对简单。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值