62.不同路径
62. 不同路径 - 力扣(LeetCode)
本题大家掌握动态规划的方法就可以。 数论方法 有点非主流,很难想到。
代码随想录
视频讲解:动态规划中如何初始化很重要!| LeetCode:62.不同路径_哔哩哔哩_bilibili
dp数组含义:从m*n格子左上角到右上角有几种走法
递推公式:dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
初始化:dp[i][1] = 1 dp[1][i] = 1
遍历顺序:从左往右
class Solution {
public int uniquePaths(int m, int n) {
int[][] dp = new int[m + 1][n + 1];
for(int i = 1;i < m + 1;i++){
dp[i][1] = 1;
}
for(int i = 1;i < n + 1;i++){
dp[1][i] = 1;
}
for(int i = 2;i < m + 1;i++){
for(int j = 2;j < n + 1;j++){
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
return dp[m][n];
}
}
63. 不同路径 II
63. 不同路径 II - 力扣(LeetCode)
https://programmercarl.com/0063.%E4%B8%8D%E5%90%8C%E8%B7%AF%E5%BE%84II.htmlhttps://programmercarl.com/0063.%E4%B8%8D%E5%90%8C%E8%B7%AF%E5%BE%84II.html
视频讲解:动态规划,这次遇到障碍了| LeetCode:63. 不同路径 II_哔哩哔哩_bilibili
dp数组含义:从当前位置到目标位置有几种走法
递归公式:dp[i][j] = dp[i + 1][j] + dp[i][j + 1];
初始化:n - 1列 m - 1行,从左向右从上到下找到最后一个出现的障碍,障碍和之前的dp都是0
其他位置如果有障碍,dp也是0
遍历顺序:从右向左,从下到上
class Solution {
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int m = obstacleGrid.length;
int n = obstacleGrid[0].length;
int[][] dp = new int[m][n];
int mem = -1;
//初始化n - 1列
for(int i = 0;i < m;i++){
if(obstacleGrid[i][n - 1] == 1){
mem = i;
dp[i][n - 1] = 0;
}
else{
dp[i][n - 1] = 1;
}
}
if(mem != -1){
for(int i = 0;i < mem;i++){
dp[i][n - 1] = 0;
}
}
mem = -1;
//初始化m - 1行
for(int i = 0;i < n;i++){
if(obstacleGrid[m - 1][i] == 1){
mem = i;
dp[m - 1][i] = 0;
}
else{
dp[m - 1][i] = 1;
}
}
if(mem != -1){
for(int i = 0;i < mem;i++){
dp[m - 1][i] = 0;
}
}
for(int i = m - 2;i >= 0;i--){
for(int j = n - 2;j >= 0;j--){
//碰到障碍就是0种走法
if(obstacleGrid[i][j] == 1)dp[i][j] = 0;
//从右向左遍历
else dp[i][j] = dp[i + 1][j] + dp[i][j + 1];
}
}
return dp[0][0];
}
}
随想录的,dp的含义是从00到该目标位置有几种走法,从左向右遍历
初始化第一行第一列,没有障碍物赋1,只要遇到一个障碍物就赋0,后面都是0
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++) {
dp[i][j] = (obstacleGrid[i][j] == 0) ? dp[i - 1][j] + dp[i][j - 1] : 0;
}
}
return dp[m - 1][n - 1];
}
}
-
整数拆分
343. 整数拆分 - 力扣(LeetCode)
代码随想录
视频讲解:动态规划,本题关键在于理解递推公式!| LeetCode:343. 整数拆分_哔哩哔哩_bilibili
class Solution {
public int integerBreak(int n) {
if(n == 2)return 1;
int[] dp = new int[n + 1];
dp[2] = 1;
dp[3] = 2;
int temp = 0;
for(int i = 3;i < n + 1;i++){
for(int j = 1;j <= i/2;j++){
dp[i] = Math.max(j * dp[i - j],j*(i - j));
dp[i] = Math.max(dp[i],temp);
temp = dp[i];
}
}
return dp[n];
}
}
-
不同的二叉搜索树 (跳过)
本题思路并不容易想,一刷建议可以跳过。 如果学有余力,可以看视频理解一波。
代码随想录
视频讲解:动态规划找到子状态之间的关系很重要!| LeetCode:96.不同的二叉搜索树_哔哩哔哩_bilibili