代码随想录刷题day34丨 62.不同路径 ,63. 不同路径 II
1.题目
1.1不同路径
-
题目链接:62. 不同路径 - 力扣(LeetCode)
-
视频讲解:动态规划中如何初始化很重要!| LeetCode:62.不同路径_哔哩哔哩_bilibili
-
文档讲解:https://programmercarl.com/0062.%E4%B8%8D%E5%90%8C%E8%B7%AF%E5%BE%84.html
-
解题思路:动态规划
-
确定dp数组(dp table)以及下标的含义
dp[i][j] :表示从(0 ,0)出发,到(i, j) 有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]一定都是1,因为从(0, 0)的位置到(i, 0)的路径只有一条,那么dp[0][j]也同理。 for (int i = 0; i < m; i++) dp[i][0] = 1; for (int j = 0; j < n; j++) dp[0][j] = 1;
-
确定遍历顺序
递推公式dp[i][j] = dp[i - 1][j] + dp[i][j - 1],dp[i][j]都是从其上方和左方推导而来, 那么从左到右一层一层遍历就可以了。
-
举例推导dp数组
-
-
代码:
//时间复杂度:O(m × n) //空间复杂度:O(m × n) 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 j = 0;j <n;j++){ dp[0][j] = 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]; } }
-
总结:
- 初始化和遍历顺序很重要!
1.2不同路径 II
-
题目链接:63. 不同路径 II - 力扣(LeetCode)
-
视频讲解:动态规划,这次遇到障碍了| LeetCode:63. 不同路径 II_哔哩哔哩_bilibili
-
文档讲解:https://programmercarl.com/0063.%E4%B8%8D%E5%90%8C%E8%B7%AF%E5%BE%84II.html
-
解题思路:动态规划
-
确定dp数组(dp table)以及下标的含义
dp[i][j] :表示从(0 ,0)出发,到(i, j) 有dp[i][j]条不同的路径。
-
确定递推公式
dp[i][j] = dp[i - 1][j] + dp[i][j - 1] 这里需要注意;(i, j)如果就是障碍的话应该就保持初始状态(初始状态为0) 所以: if(obstacleGrid[i][j] == 0){ dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; }else{ dp[i][j] = 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循环的终止条件,一旦遇到obstacleGrid[i][0] == 1的情况就停止dp[i][0]的赋值1的操作,dp[0][j]同理
-
确定遍历顺序
从左到右一层一层遍历 for(int i = 1;i < m;i++){ for(int j = 1;j < n;j++){ if(obstacleGrid[i][j] == 0){ dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; }else{ dp[i][j] = 0; } } }
-
举例推导dp数组
- 举例
-
- 对应的dp图
-
代码:
//时间复杂度:O(m × n) //空间复杂度:O(m × n) class Solution { public int uniquePathsWithObstacles(int[][] obstacleGrid) { int m = obstacleGrid.length; int n = obstacleGrid[0].length; int[][] dp = new int[m][n]; //如果在起点或终点出现了障碍,直接返回0 if (obstacleGrid[m - 1][n - 1] == 1 || obstacleGrid[0][0] == 1) { return 0; } //初始化 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] == 0){ dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; }else{ dp[i][j] = 0; } } } return dp[m - 1][n - 1]; } }
-
总结:
- 该题与题(62.不同路径)的区别在于初始化的方式不同