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

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

不同路径

62.不同路径
文章讲解:https://programmercarl.com/0062.%E4%B8%8D%E5%90%8C%E8%B7%AF%E5%BE%84.html
题目链接:https://leetcode.cn/problems/unique-paths/
视频讲解:https://www.bilibili.com/video/BV1ve4y1x7Eu/

自己看到题目的第一想法

动态规划五步骤,后面听视频去了。

看完代码随想录之后的想法

动态规划五步骤:

  • 确定dp数组(dp table)以及下标的含义
    • dp数组dp[i][j]为机器人到达i,j位置的不同路径数
  • 确定递推公式
    • 因为只能向下或者向右移动一步,因此当finish在i,j的位置上时,只有 dp[i-1,j]或者dp[i,j-1]能到达,因此dp[i,j] = dp[i-1,j] + dp[i,j-1]
  • dp数组如何初始化
    • 确定初始化值,这里可以确定起点位置如果想到达最右边或者最下边只有一条路径可以到达,因此可以将dp[0-n,0],dp[0,0-m]都初始化成1
  • 确定遍历顺序
    • 因为这里是从0,0位置出发,因此遍历是从小到大
  • 打印dp数组
public int uniquePaths(int m, int n) {
   // 1. 确定dp数组以及下标含义,dp数组dp[i][j]为机器人到达i,j位置的不同路径数
   int[][] dp = new int[n][m];
   // 2. 确定递推公式,因为只能向下或者向右移动一步,因此当finish在i,j的位置上时,只有 dp[i-1,j]或者dp[i,j-1]能到达,因此dp[i,j] = dp[i-1,j] + dp[i,j-1]
   // 3. 确定初始化值,这里可以确定起点位置如果想到达最右边或者最下边只有一条路径可以到达,因此可以将dp[0-n,0],dp[0,0-m]都初始化成1
   // 4. 因为这里是从0,0位置出发,因此遍历是从小到大
   for(int i = 0; i < n; i++) dp[i][0] = 1;
   for(int i = 0; i < m; i++) dp[0][i] = 1;
   for(int i = 1; i < n; i++){
       for(int j = 1; j < m; j++){
           dp[i][j] = dp[i-1][j] + dp[i][j-1];
           // 5. 打印测试
           System.out.println("i:" + i + ",j:" + j + "," + "dp[i][j]:" +dp[i][j]);
       }
   }
   return dp[n - 1][m - 1];

}

自己实现过程中遇到哪些困难

刚开始初始化值没想明白,后面提交一次后重新思考了下,初始值应该是从小到大去计算这样才能让遍历方法的数组有累加的结果。

不同路径 II

63. 不同路径 II
文章讲解:https://programmercarl.com/0063.%E4%B8%8D%E5%90%8C%E8%B7%AF%E5%BE%84II.html
题目链接:https://leetcode.cn/problems/unique-paths-ii/
视频讲解:https://www.bilibili.com/video/BV1Ld4y1k7c6/

自己看到题目的第一想法

动态规划五步骤去处理,和不同路径第一道题类似,但是这里没细想遇到障碍时的处理逻辑。

看完代码随想录之后的想法

动态规划五步骤:

  • 确定dp数组(dp table)以及下标的含义
    • dp数组dp[i][j]为机器人到达i,j位置的不同路径数
  • 确定递推公式
    • 因为只能向下或者向右移动一步,因此当finish在i,j的位置上时,只有 dp[i-1,j]或者dp[i,j-1]能到达,因此dp[i,j] = dp[i-1,j] + dp[i,j-1],但是这里有个关键就是当当前节点有障碍物的时候就无法进行直接跳过了
  • dp数组如何初始化
    • 这里可以确定起点位置如果想到达最右边或者最下边只有一条路径可以到达,因此可以将dp[0-n,0],dp[0,0-m]都初始化成1,同理有障碍物则跳过
  • 确定遍历顺序
    • 因为这里是从0,0位置出发,因此遍历是从小到大
  • 打印dp数组

自己实现过程中遇到哪些困难

public int uniquePathsWithObstacles(int[][] obstacleGrid) {
    // 获取m和n
    int m = obstacleGrid.length;
    int n = obstacleGrid[0].length;
    System.out.println("m:"+m+",n:"+n);
    if(obstacleGrid[0][0] == 1 || obstacleGrid[m - 1][n - 1] == 1){
        return 0;
    }
    
    // 1. 确定dp数组以及下标含义,dp数组dp[i][j]为机器人到达i,j位置的不同路径数
    int[][] dp = new int[m][n];
    // 2. 确定递推公式,因为只能向下或者向右移动一步,因此当finish在i,j的位置上时,只有 dp[i-1,j]或者dp[i,j-1]能到达,因此dp[i,j] = dp[i-1,j] + dp[i,j-1]
    // 3. 确定初始化值,这里可以确定起点位置如果想到达最右边或者最下边只有一条路径可以到达,因此可以将dp[0-n,0],dp[0,0-m]都初始化成1
    // 4. 因为这里是从0,0位置出发,因此遍历是从小到大
    for(int i = 0; i < m && obstacleGrid[i][0] != 1; i++) {
            dp[i][0] = 1;
    }
    for(int i = 0; i < n && obstacleGrid[0][i] != 1; i++){
            dp[0][i] = 1;
    }
    for(int i = 1; i < m; i++){
        for(int j = 1; j < n; j++){
            if(obstacleGrid[i][j] != 1){
                 dp[i][j] = dp[i-1][j] + dp[i][j-1];
                 // 5. 打印测试
            System.out.println("i:" + i + ",j:" + j + "," + "dp[i][j]:" +dp[i][j]);
            }else{
                continue;
            }
            
        }
    }
    return dp[m - 1][n - 1];

}

今日收获&学习时长

更加的熟悉了动态规划五步骤的处理思路。路径推倒类题目的初始值就按照从小往大遍历的逻辑处理。
学习时长:2小时

你可能感兴趣的:(算法)