【算法题】动态规划学习总结-3

78 阅读1分钟

今天的前几道题也很简单,重点是最后一题,卡了很久没想明白,看了大佬的思路后豁然开朗!

leetcode 63. 不同路径 II

image.png

思路

  • 能发拆成小问题?可以呢,就是到坐标(i,j)的路径条数
  • 后面问题只依赖前面问题的解?肯定,
  • 同样用dp[i][j]来代表到(i,j)点的路径条数
  • 这个题和之前那个基本一个思路,只不过注意障碍点的dp为0;
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
    int m = obstacleGrid.length;
    int n = obstacleGrid[0].length;
    int[][] dp = new int[m][n];
    if (obstacleGrid[0][0] == 1) return 0;
    for (int i =0;i<m;i++){
        for (int j = 0;j<n;j++){
            if (i==0 && j==0) {dp[i][j] = 1;continue;}
            if ((i==0 || j==0)){
                if (obstacleGrid[i][j] == 1) dp[i][j] = 0;
                else {dp[i][j] = i==0 ?dp[i][j-1]:dp[i-1][j];}
                continue;
            }
            if (obstacleGrid[i][j] == 1) {
                dp[i][j] = 0;
            }else {
                dp[i][j] = dp[i-1][j] + dp[i][j-1];
            }
        }
    }
    return dp[m-1][n-1];
}

leetcode 64. 最小路径和

image.png

思路

  • 能发拆成小问题?可以呢,就是到坐标(i,j)的最小路径和
  • 后面问题只依赖前面问题的解?肯定,
  • 同样用dp[i][j]来代表到(i,j)点的最小路径和
  • 这个题和上一个题那个基本一个思路,只不过(i,j)点的dp值=min(dp[i-1][j],dp[i][j]) + grid[i][j];
public int minPathSum(int[][] grid) {
    int m = grid.length;
    int n = grid[0].length;
    int[][] dp = new int[m][n];
    // 第一行和第一列,只有前面一点
    // 其他,每点只有两个前一点,去两个的dp小值 + grid值就是了
    for (int i =0;i<m;i++){
        for (int j = 0;j<n;j++){
            if (i==0 && j==0) {dp[i][j] = grid[0][0];continue;}
            if (i==0 || j==0) {
                dp[i][j] = grid[i][j];
                dp[i][j] += i==0 ?dp[i][j-1]:dp[i-1][j];
                continue;
            }
            dp[i][j] = grid[i][j] + Math.min(dp[i][j-1], dp[i-1][j]);
        }
    }
    return dp[m-1][n-1];
}

leetcode 70. 爬楼梯

image.png

  • 能发拆成小问题?可以呢,就是到第i层的跳跃方法总数
  • 后面问题只依赖前面问题的解?肯定,
  • 同样用dp[i]来代表到第i层的跳跃方法总数
  • 由于一次只能跳一个或者两个,第i层的dp值=dp[i-1] + dp[i-2];

很标准的dp算法题

public int climbStairs(int n) {
    if (n==1) return 1;
    if (n==2) return 2;
    int[]dp = new int[n];
    dp[0] = 1;
    dp[1] = 2;
    for (int i = 2;i<n;i++){
        dp[i] = dp[i-1] + dp[i-2];
    }
    return dp[n-1];
}

leetcode 45. 跳跃游戏 II

今天最难题,做这道题花了很长时间还没有ac,主要是没有很好的dp思路,直到看到一位大佬的题解,和另一位大佬的dp教学 一份给算法新人们的「动态规划」讲解

  • 能发拆成小问题?可以呢,就是到第i点的最小跳跃次数
  • 后面问题只依赖前面问题的解?肯定,
  • dp确定:
    • 定义: 用dp[i]来代表到第i点的最小跳跃次数
    • 状态转移方程:dp[i]的值应该是第一个能跳到i的点的dp值+1
    • 起始值:dp[0]=0,dp[1]=1
  • 那么我们怎么判断第一个能跳到i的点呢?如果j点的下标 + j点能跳的距离 >= i的下标,就可以认为能跳到i点,那么我们就要找尽可能小的j点
public int jump1(int[] nums) {
    int[] dp = new int[nums.length];
    dp[0] = 0;
    int j = 0;
    for (int i = 1; i < nums.length; i++) {
        while(j + nums[j] < i){
            j++;
        }
        dp[i] = dp[j] + 1;
    }
    return dp[nums.length - 1];
}