62.不同路径
本题大家掌握动态规划的方法就可以。 数论方法 有点非主流,很难想到。
leetcode题目链接
题目链接/文章讲解
视频讲解
二叉树的深度搜索,找到总共有几个叶子节点的值是dp[m][n]
二叉树的节点定义:二叉树的每一个节点的左节点是向右移动,右节点是向下移动。
每一层的含义:这样每一层就是向下,向右移动的所有情况,这里也是回溯算法的用法。
每向下一层含义:每向下一层,就是向下,向右各移动一步,对应数组就是dp[i][j],就是i + 1 并且 j + 1
根节点到叶子节点的路径的含义:每条路径就是到目标值的所有路径
class Solution {
private:
int dfs(int i, int j, int m, int n) {
if (i > m || j > n) return 0; // 越界了
if (i == m && j == n) return 1; // 找到一种方法,相当于找到了叶子节点
int left = dfs(i + 1, j, m, n);// i 向右移动,后递归
//这里有I回溯,j +1
int right = dfs(i, j + 1, m, n);
return left + right;
}
public:
int uniquePaths(int m, int n) {
return dfs(1, 1, m, n);
}
};
动态规划五步曲
-
确定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-1][j]过来的,从上边过来的一定是从dp[i][j -1]过来的
此时在回顾一下 dp[i - 1][j] 表示啥,是从(0, 0)的位置到(i - 1, j)有几条路径,dp[i][j - 1]同理。
那么很自然,dp[i][j] = dp[i - 1][j] + dp[i][j - 1],因为dp[i][j]只有这两个方向过来。
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;
4.遍历顺序是从前往后遍历
class Solution {
public:
int uniquePaths(int m, int n) {
vector<vector<int>> dp(m, vector<int>(n,0));
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][j-1] + dp[i -1][j];
}
}
return dp[m-1][n-1];
}
};
63. 不同路径 II
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
int m = obstacleGrid.size();
int n = obstacleGrid[0].size();
vector<vector<int>> dp(m, vector<int>(n, 0));
//如果起始位置和重点位置有障碍,没有路径可以到达
if(obstacleGrid[0][0] == 1 || obstacleGrid[m-1][n-1] == 1) {
return 0;
}
for(int i = 0; i < m && obstacleGrid[i][0] != 1; i ++) {
dp[i][0] = 1;
}
for(int j = 0; j < n && obstacleGrid[0][j] != 1; j++) {
dp[0][j] = 1;
}
for(int i = 1; i < m; i ++) {
for(int j = 1; j < n; j ++) {
//如果下标对应的位置有障碍说明这条路线不能到达终点所以需要跳过
if(obstacleGrid[i][j] == 1) continue;
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
//下标从0开始所以都需要减一
return dp[m-1][n-1];
}
};