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

目录

62.不同路径

 63. 不同路径 II


今天开始逐渐有 dp的感觉了,题目不多,就两个 不同路径,可以好好研究一下

62.不同路径

本题大家掌握动态规划的方法就可以。 数论方法 有点非主流,很难想到。

代码随想录

视频讲解:动态规划中如何初始化很重要!| LeetCode:62.不同路径_哔哩哔哩_bilibili

题解思路:

看完卡哥视频题解还是思路蛮清晰的,还是只依赖于上一步的结果去判断下一步的结果,这里一定需要理解清楚dp[i][j]的含义:从(0,0)走到(i,j)总共有多少种不同的路径,才好明白为什么初始化dp[0][n] = 1, dp[m][0] = 1,因为这里dp数组的含义是路径的方法,不是步数,不是步数,不是步数!!!当确定好只能向右方向走的时候,不管走到[0][n]那个格子,只有一种路径方法;当确定好只能向下方向走的时候,不管走到[m][0]那个格子,也只有一种路径方法。所以按照这种思路去考虑dp数组初始化的值!!!

class Solution {
    public int uniquePaths(int m, int n) {
        //动规第一步:确定dp[i][j]含义:从(0,0)走到(i,j)总共有多少种不同的路径
        //动规第二步:确定递推公式dp[i][j] = dp[i-1][j](从上往下走,计算从(0,0)到(i-1, j)不同的路径的总和) + dp[i][j-1](从左往右走,计算从(0,0)到(i,j-1)不同的路径总和),因为题目规定只能向下或者向右走
        //动规第三步:数组初始化,因为dp[0][n] = 1, dp[m][0] = 1
        //动规第四步:确定遍历顺序,因为当前状态由上一个状态确定的,因此需要从前往后遍历
        //动规第五步:打印dp数组,检查逻辑正确与否

        int[][] dp = new int[m][n];
        //初始化数组
        for(int i = 0; i < m; i++){
            dp[i][0] = 1;
        }
        for(int i = 0; i < n; i++){
            dp[0][i] = 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];
    }
}

 63. 不同路径 II

代码随想录

视频讲解:https://www.bilibili.com/video/BV1Ld4y1k7c6

题解思路:

本题思路和62.不同路径一样,只不过多了一个障碍物的判断,只不过需要根据给定障碍物网格进行dp数组的初始化,以及结果的计算方式!!!具体的判断条件见代码注释!!!

class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int m = obstacleGrid.length; //获取网格的行数
        int n = obstacleGrid[0].length; //获取网格的列数

        int[][] dp = new int[m][n];
        //初始化dp数组
        for(int i = 0; i < m; i++){
            if(obstacleGrid[i][0] == 1){
                break;  //一旦遇到障碍物网格第0列的i行值是0时,后面就没必要再初始化了,因为不可能到达的
            }  
            dp[i][0] = 1;
        }
        for(int i = 0; i < n; i++){
            if(obstacleGrid[0][i] == 1){
                break; //一旦遇到障碍物网格第0行第i列值是0时,后面就没必要再初始化了,因为不可能到达的
            }
            dp[0][i] = 1;
        }

        for(int i = 1; i < m; i++){
            for(int j = 1; j < n; j++){
                if(obstacleGrid[i][j-1] != 1 && obstacleGrid[i - 1][j] == 1){
                    dp[i][j] = dp[i][j-1]; //当前的位置的上方有障碍,但是当前位置的左边没障碍的时候,只能走左边那条道
                }else if(obstacleGrid[i][j-1] == 1 && obstacleGrid[i - 1][j] != 1){
                    dp[i][j] = dp[i-1][j];  //当前的位置的上方没有障碍,当前位置的左边有障碍的时候,只能走上方那条道
                }else if(obstacleGrid[i][j-1] != 1 && obstacleGrid[i - 1][j] != 1 && obstacleGrid[i][j] != 1){
                    dp[i][j] = dp[i][j-1] + dp[i-1][j]; //当前的位置的上方没有障碍,当前位置的左边也没有障碍的时候,可以选择走上方和走左边两条道,
               //这里还有一个特殊的判断,以[[0,0][0,1]]特例说明,此时第0行和第0列所在的格子都可以初始化值为1,但是(1,1)这个位置本来就有障碍物了,因此返回值就是0,那么在判断条件上需要加上终点位置不为1的判断条件,此时返回的结果才是正确的!!!
                }
            }
        }
        return dp[m -1][n - 1];

    }
}

猜你喜欢

转载自blog.csdn.net/tore007/article/details/131010231
今日推荐