代码随想录动态规划 62 63

Day34

62.不同路径

力扣题目链接

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。

问总共有多少条不同的路径?

思路

  • 可以使用排列组合处理,计算后发现

$$

C_{m+n-2}^{m-1}

$$

  • 带入计算即可,需要注意int溢出和除的时候可能有舍入误差,从1开始除,先用long接收,最后转为int

  • 动态规划

  • 确定dp数组(dp table)以及下标的含义

  • dp[i] [j]指的是运动到这个点的所有路径可能

  • 确定递推公式

  • dp[i] [j]可能从dp[i - 1] [j]走来,也可能从dp[i] [j - 1]走来,因此dp[i] [j] = dp[i - 1] [j] + dp[i] [j - 1]

  • dp数组如何初始化

  • 第一行和第一列只有一种路径可走,因此dp[i] [0] = dp[0] [j] = 1

  • 确定遍历顺序

  • 从左向右遍历即可

  • 举例推导dp数组

代码

class Solution {
    public int uniquePaths(int m, int n) {
        long temp1 = m + n - 2;//分子最开始是m + n - 2
        long temp2 = 1;//从1开始除
        long res = 1;
        while (temp2 <= Math.min(m - 1, n - 1)){
            res =  res * temp1 / temp2;//防止溢出,乘一个除一个
            temp1--;
            temp2++;
        }
        return (int)res;//最后转为int输出
    }
}

class Solution {
    public int uniquePaths(int m, int n) {
        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

力扣题目链接

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。

现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?

思路

  • 和上一题的区别是,有障碍物了

  • 重点是,在初始化时如果遇到障碍物,那么障碍物位置和后续这一行或这一列的所有位置都是0

  • 遍历时如果遇到障碍物,这个位置就是0,不是障碍物就是上位置和左位置元素和

代码

class Solution {
    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 || obstacleGrid[m - 1][n - 1] == 1) return 0;//起点或终点有障碍物,返回0
        for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++) {
            dp[i][0] = 1;//注意逻辑,如果某个位置有障碍物了,直接退出循环了,后面的都是数组元素初始值0
        }
        for (int i = 0; i < n && obstacleGrid[0][i] == 0; i++) {
            dp[0][i] = 1;
        }
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                dp[i][j] = (obstacleGrid[i][j] == 1) ? 0 : dp[i - 1][j] + dp[i][j - 1];//需要考虑是否有障碍物
            }
        }
        return dp[m - 1][n - 1];
    }
}

你可能感兴趣的:(动态规划,算法,leetcode)