【C++编程能力提升】

代码随想录训练营Day39 | Leetcode 62、63

一、62 不同路径

题目链接:62 不同路径

核心:当前位置只能由左边位置(向右走)或者上边位置(向下走)这两条路径得到。
第一,dp数组的定义:dp[i][j]表示从起点(0,0)到位置(i,j)的不同路径数;
第二,递推公式:dp[i][j]=dp[i-1][j]+dp[i][j-1];当前位置的不同路径数为左边和上边位置的不同路径数之和;
第三,初始化:第一行和第一列的路径都只有一条,前者是一直往右走,后者是一直往下走,故第一行和第一列的元素都初始化为1;
第四,遍历顺序,从上到下,从左到右,且从第二行第二列的第一个元素开始遍历。
注意:优化空间的处理,即只用一维数组记录不同路径数(滚动数组),统计当前行的数据时会覆盖上一行的数据,因此当前位置为当前位置(未被覆盖)和左边位置元素之和。

    int uniquePaths(int m, int n) {
        //动态规划
        //优化空间,只用一维dp数组
        vector<int> dp(n);  //记录每一行的数据,下一行会覆盖上一行
        for(int i=0;i<n;++i)
            dp[i]=1;    //第一行数据初始化为1
        for(int j=1;j<m;++j)
        {//从第二行开始遍历,当前位置为当前位置(上一行)和左边位置(左一列)之和
            for(int i=1;i<n;++i)
                dp[i]+=dp[i-1];
        }
        return dp[n-1];

        /*
        vector<vector<int>> dp(m,vector<int>(n,0));  //dp数组,记录i,j位置的路径数
        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)
        {//从i=1和j=1开始从左往右从上到下依次统计dp数组
            for(int j=1;j<n;++j)
                dp[i][j]=dp[i-1][j]+dp[i][j-1]; //当前位置可由上一次的左边往右走或者上边往下走
        }
        return dp[m-1][n-1];
        */
    }

二、63 不同路径II

题目链接:63 不同路径II

核心:当前位置只能从左边位置或上边位置得到,且不存在障碍物,因为一旦遇到障碍物表示这条路径不通,即令当前位置元素为0.
第一,dp数组的定义:dp[i][j]记录当前位置(i,j)的不同路径数;
第二,递归公式:依然是dp[i][j]=dp[i-1][j]+dp[i][j-1],但存在条件,即不存在障碍物,如果遇到障碍物则令其为0(由于最初定义dp数组时就令所有元素为0,因此遍历时遇到障碍物直接continue,无需处理该位置的元素值。)
第三,初始化:第一行和第一列且不存在障碍物的位置均初始化为1,存在障碍物的位置依然为0;
第四,遍历顺序:从上到下,从左到右依次遍历。
(起点或终点存在障碍物都直接返回0,表示不存在可通的路径)
注意:优化空间的处理,不仅在遍历时对障碍物进行处理,而在初始化第一行元素时也需要对障碍物进行处理,即在第一行中如果遇到障碍物则令其为0,未遇到障碍物时,第一个位置则初始化为1,其他位置不是直接初始化为1,而是继承相邻左边位置的元素值(因为可能相邻左边是障碍物)。

    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        //动态规划,遇到障碍需赋值为0,或者无需更新当前位置(因初始化已经为0)
        //优化空间
        int m=obstacleGrid.size();      //row
        int n=obstacleGrid[0].size();   //col
        if(obstacleGrid[0][0]==1 || obstacleGrid[m-1][n-1]==1)
            return 0;       //起点或终点有障碍物,则不存在路径
        vector<int> dp(n,0);    //一维数组,记录每一行数据,下一行覆盖上一行
        for(int j=0;j<n; ++j)
        {//第一行初始化:遇到障碍物令其为0,以及障碍物之后的位置都为0
            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)
            {//从第二列的第一个位置开始,因为第一个位置可能有障碍物,不能默认为1
                if(obstacleGrid[i][j]==1)
                    dp[j]=0;    //遇到障碍物则令其为0
                else if(j!=0)
                    dp[j]+=dp[j-1]; //没有障碍物且不是第一个位置
            }
        }
        return dp[n-1];
        /*
        int m=obstacleGrid.size();      //row
        int n=obstacleGrid[0].size();   //col
        if(obstacleGrid[0][0]==1 || obstacleGrid[m-1][n-1]==1)
            return 0;       //起点或终点有障碍物,则不存在路径
        vector<vector<int>> dp(m,vector<int>(n,0)); //dp数组初始化为0
        //初始化第一行和第一列dp数组时需考虑障碍情况
        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;   //遇到障碍则跳过此位置,无需更新,即该位置仍为0
                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、付费专栏及课程。

余额充值