This commit is contained in:
youngyangyang04
2021-08-13 09:43:54 +08:00
parent 0207c1a471
commit c64934459c
2 changed files with 178 additions and 223 deletions

View File

@ -122,8 +122,8 @@
## 社群 ## 社群
* [准备秋招的录友们,组织在这里](https://mp.weixin.qq.com/s/xX4LFwZQIG_XiQAxVBrfeA) * [准备秋招的录友们,组织在这里](https://mp.weixin.qq.com/s/xX4LFwZQIG_XiQAxVBrfeA)
* [准备社招的录友们,组织在这里!](https://mp.weixin.qq.com/s/mbQ3s17ZJ4LXFRb-VD58Ww)
## 知识星球精选 ## 知识星球精选
@ -146,10 +146,13 @@
## 杂谈 ## 杂谈
* [「代码随想录」刷题网站上线](https://mp.weixin.qq.com/s/-6rd_g7LrVD1fuKBYk2tXQ)。
* [LeetCode-Master上榜了](https://mp.weixin.qq.com/s/wZRTrA9Rbvgq1yEkSw4vfQ) * [LeetCode-Master上榜了](https://mp.weixin.qq.com/s/wZRTrA9Rbvgq1yEkSw4vfQ)
* [上榜之后,都有哪些变化?](https://mp.weixin.qq.com/s/VJBV0qSBthjnbbmW-lctLA)
* [大半年过去了......](https://mp.weixin.qq.com/s/lubfeistPxBLSQIe5XYg5g) * [大半年过去了......](https://mp.weixin.qq.com/s/lubfeistPxBLSQIe5XYg5g)
* [一万录友在B站学算法](https://mp.weixin.qq.com/s/Vzq4zkMZY7erKeu0fqGLgw) * [一万录友在B站学算法](https://mp.weixin.qq.com/s/Vzq4zkMZY7erKeu0fqGLgw)
## 数组 ## 数组
1. [数组过于简单,但你该了解这些!](./problems/数组理论基础.md) 1. [数组过于简单,但你该了解这些!](./problems/数组理论基础.md)
@ -248,7 +251,7 @@
15. [二叉树:以为使用了递归,其实还隐藏着回溯](./problems/二叉树中递归带着回溯.md) 15. [二叉树:以为使用了递归,其实还隐藏着回溯](./problems/二叉树中递归带着回溯.md)
16. [二叉树:做了这么多题目了,我的左叶子之和是多少?](./problems/0404.左叶子之和.md) 16. [二叉树:做了这么多题目了,我的左叶子之和是多少?](./problems/0404.左叶子之和.md)
17. [二叉树:我的左下角的值是多少?](./problems/0513.找树左下角的值.md) 17. [二叉树:我的左下角的值是多少?](./problems/0513.找树左下角的值.md)
18. [二叉树:递归函数究竟什么时候需要返回值,什么时候不要返回值?](./problems/0112.路径总和.md) 18. [二叉树:路径总和](./problems/0112.路径总和.md)
19. [二叉树:构造二叉树登场!](./problems/0106.从中序与后序遍历序列构造二叉树.md) 19. [二叉树:构造二叉树登场!](./problems/0106.从中序与后序遍历序列构造二叉树.md)
20. [二叉树:构造一棵最大的二叉树](./problems/0654.最大二叉树.md) 20. [二叉树:构造一棵最大的二叉树](./problems/0654.最大二叉树.md)
21. [本周小结!(二叉树系列三)](./problems/周总结/20201010二叉树周末总结.md) 21. [本周小结!(二叉树系列三)](./problems/周总结/20201010二叉树周末总结.md)

View File

@ -9,14 +9,14 @@
> 递归函数什么时候需要返回值 > 递归函数什么时候需要返回值
相信很多同学都会疑惑递归函数什么时候要有返回值什么时候没有返回值特别是有的时候递归函数返回类型为bool类型。那么 相信很多同学都会疑惑递归函数什么时候要有返回值什么时候没有返回值特别是有的时候递归函数返回类型为bool类型。
接下来我通过详细讲解如下两道题,来回答这个问题: 那么接下来我通过详细讲解如下两道题,来回答这个问题:
* 112.路径总和 * 112.路径总和
* 113.路径总和II * 113.路径总和ii
## 112. 路径总和 # 112. 路径总和
题目地址https://leetcode-cn.com/problems/path-sum/ 题目地址https://leetcode-cn.com/problems/path-sum/
@ -31,11 +31,11 @@
返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。 返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。
### 思路 # 思路
这道题我们要遍历从根节点到叶子节点的的路径看看总和是不是目标和。 这道题我们要遍历从根节点到叶子节点的的路径看看总和是不是目标和。
### 递归 ## 递归
可以使用深度优先遍历的方式(本题前中后序都可以,无所谓,因为中节点也没有处理逻辑)来遍历二叉树 可以使用深度优先遍历的方式(本题前中后序都可以,无所谓,因为中节点也没有处理逻辑)来遍历二叉树
@ -43,13 +43,11 @@
参数需要二叉树的根节点还需要一个计数器这个计数器用来计算二叉树的一条边之和是否正好是目标和计数器为int型。 参数需要二叉树的根节点还需要一个计数器这个计数器用来计算二叉树的一条边之和是否正好是目标和计数器为int型。
**再来看返回值,递归函数什么时候需要返回值?什么时候不需要返回值?** 再来看返回值,递归函数什么时候需要返回值?什么时候不需要返回值?这里总结如下三点:
在文章[二叉树:我的左下角的值是多少?](https://mp.weixin.qq.com/s/MH2gbLvzQ91jHPKqiub0Nw)中,我给出了一个结论: * 如果需要搜索整颗二叉树且不用处理递归返回值递归函数就不要返回值。这种情况就是本文下半部分介绍的113.路径总和ii
* 如果需要搜索整颗二叉树且需要处理递归返回值,递归函数就需要返回值。 (这种情况我们在[236. 二叉树的最近公共祖先](https://mp.weixin.qq.com/s/n6Rk3nc_X3TSkhXHrVmBTQ)中介绍)
**如果需要搜索整颗二叉树,那么递归函数就不要返回值,如果要搜索其中一条符合条件的路径,递归函数就需要返回值,因为遇到符合条件的路径了就要及时返回。** * 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。(本题的情况)
在[二叉树:我的左下角的值是多少?](https://mp.weixin.qq.com/s/MH2gbLvzQ91jHPKqiub0Nw)中,因为要遍历树的所有路径,找出深度最深的叶子节点,所以递归函数不要返回值。
而本题我们要找一条符合条件的路径,所以递归函数需要返回值,及时返回,那么返回类型是什么呢? 而本题我们要找一条符合条件的路径,所以递归函数需要返回值,及时返回,那么返回类型是什么呢?
@ -62,7 +60,7 @@
所以代码如下: 所以代码如下:
``` ```
bool traversal(TreeNode* cur, int count) // 注意函数的返回类型 bool traversal(treenode* cur, int count) // 注意函数的返回类型
``` ```
@ -91,7 +89,7 @@ if (!cur->left && !cur->right) return false; // 遇到叶子节点而没有找
代码如下: 代码如下:
```CPP ```cpp
if (cur->left) { // 左 (空节点不遍历) if (cur->left) { // 左 (空节点不遍历)
// 遇到叶子节点返回true则直接返回true // 遇到叶子节点返回true则直接返回true
if (traversal(cur->left, count - cur->left->val)) return true; // 注意这里有回溯的逻辑 if (traversal(cur->left, count - cur->left->val)) return true; // 注意这里有回溯的逻辑
@ -109,7 +107,7 @@ return false;
为了把回溯的过程体现出来,可以改为如下代码: 为了把回溯的过程体现出来,可以改为如下代码:
```CPP ```cpp
if (cur->left) { // 左 if (cur->left) { // 左
count -= cur->left->val; // 递归,处理节点; count -= cur->left->val; // 递归,处理节点;
if (traversal(cur->left, count)) return true; if (traversal(cur->left, count)) return true;
@ -126,10 +124,10 @@ return false;
整体代码如下: 整体代码如下:
```CPP ```cpp
class Solution { class solution {
private: private:
bool traversal(TreeNode* cur, int count) { bool traversal(treenode* cur, int count) {
if (!cur->left && !cur->right && count == 0) return true; // 遇到叶子节点并且计数为0 if (!cur->left && !cur->right && count == 0) return true; // 遇到叶子节点并且计数为0
if (!cur->left && !cur->right) return false; // 遇到叶子节点直接返回 if (!cur->left && !cur->right) return false; // 遇到叶子节点直接返回
@ -147,8 +145,8 @@ private:
} }
public: public:
bool hasPathSum(TreeNode* root, int sum) { bool haspathsum(treenode* root, int sum) {
if (root == NULL) return false; if (root == null) return false;
return traversal(root, sum - root->val); return traversal(root, sum - root->val);
} }
}; };
@ -156,15 +154,15 @@ public:
以上代码精简之后如下: 以上代码精简之后如下:
```CPP ```cpp
class Solution { class solution {
public: public:
bool hasPathSum(TreeNode* root, int sum) { bool haspathsum(treenode* root, int sum) {
if (root == NULL) return false; if (root == null) return false;
if (!root->left && !root->right && sum == root->val) { if (!root->left && !root->right && sum == root->val) {
return true; return true;
} }
return hasPathSum(root->left, sum - root->val) || hasPathSum(root->right, sum - root->val); return haspathsum(root->left, sum - root->val) || haspathsum(root->right, sum - root->val);
} }
}; };
``` ```
@ -172,43 +170,43 @@ public:
**是不是发现精简之后的代码,已经完全看不出分析的过程了,所以我们要把题目分析清楚之后,在追求代码精简。** 这一点我已经强调很多次了! **是不是发现精简之后的代码,已经完全看不出分析的过程了,所以我们要把题目分析清楚之后,在追求代码精简。** 这一点我已经强调很多次了!
### 迭代 ## 迭代
如果使用栈模拟递归的话,那么如果做回溯呢? 如果使用栈模拟递归的话,那么如果做回溯呢?
**此时栈里一个元素不仅要记录该节点指针,还要记录从头结点到该节点的路径数值总和。** **此时栈里一个元素不仅要记录该节点指针,还要记录从头结点到该节点的路径数值总和。**
C++就我们用pair结构来存放这个栈里的元素。 c++就我们用pair结构来存放这个栈里的元素。
定义为:`pair<TreeNode*, int>` pair<节点指针路径数值> 定义为:`pair<treenode*, int>` pair<节点指针路径数值>
这个为栈里的一个元素。 这个为栈里的一个元素。
如下代码是使用栈模拟的前序遍历,如下:(详细注释) 如下代码是使用栈模拟的前序遍历,如下:(详细注释)
```CPP ```cpp
class Solution { class solution {
public: public:
bool hasPathSum(TreeNode* root, int sum) { bool haspathsum(treenode* root, int sum) {
if (root == NULL) return false; if (root == null) return false;
// 此时栈里要放的是pair<节点指针,路径数值> // 此时栈里要放的是pair<节点指针,路径数值>
stack<pair<TreeNode*, int>> st; stack<pair<treenode*, int>> st;
st.push(pair<TreeNode*, int>(root, root->val)); st.push(pair<treenode*, int>(root, root->val));
while (!st.empty()) { while (!st.empty()) {
pair<TreeNode*, int> node = st.top(); pair<treenode*, int> node = st.top();
st.pop(); st.pop();
// 如果该节点是叶子节点了同时该节点的路径数值等于sum那么就返回true // 如果该节点是叶子节点了同时该节点的路径数值等于sum那么就返回true
if (!node.first->left && !node.first->right && sum == node.second) return true; if (!node.first->left && !node.first->right && sum == node.second) return true;
// 右节点,压进去一个节点的时候,将该节点的路径数值也记录下来 // 右节点,压进去一个节点的时候,将该节点的路径数值也记录下来
if (node.first->right) { if (node.first->right) {
st.push(pair<TreeNode*, int>(node.first->right, node.second + node.first->right->val)); st.push(pair<treenode*, int>(node.first->right, node.second + node.first->right->val));
} }
// 左节点,压进去一个节点的时候,将该节点的路径数值也记录下来 // 左节点,压进去一个节点的时候,将该节点的路径数值也记录下来
if (node.first->left) { if (node.first->left) {
st.push(pair<TreeNode*, int>(node.first->left, node.second + node.first->left->val)); st.push(pair<treenode*, int>(node.first->left, node.second + node.first->left->val));
} }
} }
return false; return false;
@ -216,9 +214,9 @@ public:
}; };
``` ```
如果大家完全理解了本地的递归方法之后就可以顺便把leetcode上113. 路径总和II做了。 如果大家完全理解了本地的递归方法之后就可以顺便把leetcode上113. 路径总和ii做了。
## 113. 路径总和II # 113. 路径总和ii
题目地址https://leetcode-cn.com/problems/path-sum-ii/ 题目地址https://leetcode-cn.com/problems/path-sum-ii/
@ -230,26 +228,27 @@ public:
给定如下二叉树以及目标和 sum = 22 给定如下二叉树以及目标和 sum = 22
![113.路径总和II1.png](https://img-blog.csdnimg.cn/20210203160854654.png) ![113.路径总和ii1.png](https://img-blog.csdnimg.cn/20210203160854654.png)
### 思路 ## 思路
113.路径总和II要遍历整个树找到所有路径**所以递归函数不要返回值!**
113.路径总和ii要遍历整个树找到所有路径**所以递归函数不要返回值!**
如图: 如图:
![113.路径总和II](https://img-blog.csdnimg.cn/20210203160922745.png) ![113.路径总和ii](https://img-blog.csdnimg.cn/20210203160922745.png)
为了尽可能的把细节体现出来,我写出如下代码(**这份代码并不简洁,但是逻辑非常清晰** 为了尽可能的把细节体现出来,我写出如下代码(**这份代码并不简洁,但是逻辑非常清晰**
```CPP ```cpp
class Solution { class solution {
private: private:
vector<vector<int>> result; vector<vector<int>> result;
vector<int> path; vector<int> path;
// 递归函数不需要返回值,因为我们要遍历整个树 // 递归函数不需要返回值,因为我们要遍历整个树
void traversal(TreeNode* cur, int count) { void traversal(treenode* cur, int count) {
if (!cur->left && !cur->right && count == 0) { // 遇到了叶子节点且找到了和为sum的路径 if (!cur->left && !cur->right && count == 0) { // 遇到了叶子节点且找到了和为sum的路径
result.push_back(path); result.push_back(path);
return; return;
@ -275,10 +274,10 @@ private:
} }
public: public:
vector<vector<int>> pathSum(TreeNode* root, int sum) { vector<vector<int>> pathsum(treenode* root, int sum) {
result.clear(); result.clear();
path.clear(); path.clear();
if (root == NULL) return result; if (root == null) return result;
path.push_back(root->val); // 把根节点放进路径 path.push_back(root->val); // 把根节点放进路径
traversal(root, sum - root->val); traversal(root, sum - root->val);
return result; return result;
@ -286,11 +285,11 @@ public:
}; };
``` ```
至于113. 路径总和II 的迭代法我并没有写,用迭代方式记录所有路径比较麻烦,也没有必要,如果大家感兴趣的话,可以再深入研究研究。 至于113. 路径总和ii 的迭代法我并没有写,用迭代方式记录所有路径比较麻烦,也没有必要,如果大家感兴趣的话,可以再深入研究研究。
## 总结 # 总结
本篇通过leetcode上112. 路径总和 和 113. 路径总和II 详细的讲解了 递归函数什么时候需要返回值,什么不需要返回值。 本篇通过leetcode上112. 路径总和 和 113. 路径总和ii 详细的讲解了 递归函数什么时候需要返回值,什么不需要返回值。
这两道题目是掌握这一知识点非常好的题目,大家看完本篇文章再去做题,就会感受到搜索整棵树和搜索某一路径的差别。 这两道题目是掌握这一知识点非常好的题目,大家看完本篇文章再去做题,就会感受到搜索整棵树和搜索某一路径的差别。
@ -299,31 +298,30 @@ public:
# 其他语言版本
## java
## 其他语言版本 lc112
```java
class solution {
Java public boolean haspathsum(treenode root, int targetsum) {
```Java
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if (root == null) { if (root == null) {
return false; return false;
} }
targetSum -= root.val; targetsum -= root.val;
// 叶子结点 // 叶子结点
if (root.left == null && root.right == null) { if (root.left == null && root.right == null) {
return targetSum == 0; return targetsum == 0;
} }
if (root.left != null) { if (root.left != null) {
boolean left = hasPathSum(root.left, targetSum); boolean left = haspathsum(root.left, targetsum);
if (left) {// 已经找到 if (left) {// 已经找到
return true; return true;
} }
} }
if (root.right != null) { if (root.right != null) {
boolean right = hasPathSum(root.right, targetSum); boolean right = haspathsum(root.right, targetsum);
if (right) {// 已经找到 if (right) {// 已经找到
return true; return true;
} }
@ -332,34 +330,34 @@ class Solution {
} }
} }
// LC112 简洁方法 // lc112 简洁方法
class Solution { class solution {
public boolean hasPathSum(TreeNode root, int targetSum) { public boolean haspathsum(treenode root, int targetsum) {
if (root == null) return false; // 为空退出 if (root == null) return false; // 为空退出
// 叶子节点判断是否符合 // 叶子节点判断是否符合
if (root.left == null && root.right == null) return root.val == targetSum; if (root.left == null && root.right == null) return root.val == targetsum;
// 求两侧分支的路径和 // 求两侧分支的路径和
return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val); return haspathsum(root.left, targetsum - root.val) || haspathsum(root.right, targetsum - root.val);
} }
} }
``` ```
迭代 迭代
```java ```java
class Solution { class solution {
public boolean hasPathSum(TreeNode root, int targetSum) { public boolean haspathsum(treenode root, int targetsum) {
if(root==null)return false; if(root==null)return false;
Stack<TreeNode> stack1 = new Stack<>(); stack<treenode> stack1 = new stack<>();
Stack<Integer> stack2 = new Stack<>(); stack<integer> stack2 = new stack<>();
stack1.push(root);stack2.push(root.val); stack1.push(root);stack2.push(root.val);
while(!stack1.isEmpty()){ while(!stack1.isempty()){
int size = stack1.size(); int size = stack1.size();
for(int i=0;i<size;i++){ for(int i=0;i<size;i++){
TreeNode node = stack1.pop();int sum=stack2.pop(); treenode node = stack1.pop();int sum=stack2.pop();
// 如果该节点是叶子节点了同时该节点的路径数值等于sum那么就返回true // 如果该节点是叶子节点了同时该节点的路径数值等于sum那么就返回true
if(node.left==null && node.right==null && sum==targetSum)return true; if(node.left==null && node.right==null && sum==targetsum)return true;
// 右节点,压进去一个节点的时候,将该节点的路径数值也记录下来 // 右节点,压进去一个节点的时候,将该节点的路径数值也记录下来
if(node.right!=null){ if(node.right!=null){
stack1.push(node.right);stack2.push(sum+node.right.val); stack1.push(node.right);stack2.push(sum+node.right.val);
@ -380,81 +378,74 @@ class Solution {
0113.路径总和-ii 0113.路径总和-ii
```java ```java
class Solution { class solution {
public List<List<Integer>> pathSum(TreeNode root, int targetSum) { public list<list<integer>> pathsum(treenode root, int targetsum) {
List<List<Integer>> res = new ArrayList<>(); list<list<integer>> res = new arraylist<>();
if (root == null) return res; // 非空判断 if (root == null) return res; // 非空判断
List<Integer> path = new LinkedList<>(); list<integer> path = new linkedlist<>();
preorderDFS(root, targetSum, res, path); preorderdfs(root, targetsum, res, path);
return res; return res;
} }
public void preorderDFS(TreeNode root, int targetSum, List<List<Integer>> res, List<Integer> path) { public void preorderdfs(treenode root, int targetsum, list<list<integer>> res, list<integer> path) {
path.add(root.val); path.add(root.val);
// 遇到了叶子节点 // 遇到了叶子节点
if (root.left == null && root.right == null) { if (root.left == null && root.right == null) {
// 找到了和为 targetSum 的路径 // 找到了和为 targetsum 的路径
if (targetSum - root.val == 0) { if (targetsum - root.val == 0) {
res.add(new ArrayList<>(path)); res.add(new arraylist<>(path));
} }
return; // 如果和不为 targetSum返回 return; // 如果和不为 targetsum返回
} }
if (root.left != null) { if (root.left != null) {
preorderDFS(root.left, targetSum - root.val, res, path); preorderdfs(root.left, targetsum - root.val, res, path);
path.remove(path.size() - 1); // 回溯 path.remove(path.size() - 1); // 回溯
} }
if (root.right != null) { if (root.right != null) {
preorderDFS(root.right, targetSum - root.val, res, path); preorderdfs(root.right, targetsum - root.val, res, path);
path.remove(path.size() - 1); // 回溯 path.remove(path.size() - 1); // 回溯
} }
} }
} }
``` ```
Python ## python
0112.路径总和 0112.路径总和
**递归** **递归**
```python ```python
# Definition for a binary tree node. class solution:
# class TreeNode: def haspathsum(self, root: treenode, targetsum: int) -> bool:
# def __init__(self, val=0, left=None, right=None): def isornot(root, targetsum) -> bool:
# self.val = val if (not root.left) and (not root.right) and targetsum == 0:
# self.left = left return true # 遇到叶子节点并且计数为0
# self.right = right
class Solution:
def hasPathSum(self, root: TreeNode, targetSum: int) -> bool:
def isornot(root, targetSum) -> bool:
if (not root.left) and (not root.right) and targetSum == 0:
return True # 遇到叶子节点并且计数为0
if (not root.left) and (not root.right): if (not root.left) and (not root.right):
return False # 遇到叶子节点计数不为0 return false # 遇到叶子节点计数不为0
if root.left: if root.left:
targetSum -= root.left.val # 左节点 targetsum -= root.left.val # 左节点
if isornot(root.left, targetSum): return True # 递归,处理左节点 if isornot(root.left, targetsum): return true # 递归,处理左节点
targetSum += root.left.val # 回溯 targetsum += root.left.val # 回溯
if root.right: if root.right:
targetSum -= root.right.val # 右节点 targetsum -= root.right.val # 右节点
if isornot(root.right, targetSum): return True # 递归,处理右节点 if isornot(root.right, targetsum): return true # 递归,处理右节点
targetSum += root.right.val # 回溯 targetsum += root.right.val # 回溯
return False return false
if root == None: if root == none:
return False # 别忘记处理空TreeNode return false # 别忘记处理空treenode
else: else:
return isornot(root, targetSum - root.val) return isornot(root, targetsum - root.val)
``` ```
**迭代 - 层序遍历** **迭代 - 层序遍历**
```python ```python
class Solution: class solution:
def hasPathSum(self, root: TreeNode, targetSum: int) -> bool: def haspathsum(self, root: treenode, targetsum: int) -> bool:
if not root: if not root:
return False return false
stack = [] # [(当前节点,路径数值), ...] stack = [] # [(当前节点,路径数值), ...]
stack.append((root, root.val)) stack.append((root, root.val))
@ -462,8 +453,8 @@ class Solution:
while stack: while stack:
cur_node, path_sum = stack.pop() cur_node, path_sum = stack.pop()
if not cur_node.left and not cur_node.right and path_sum == targetSum: if not cur_node.left and not cur_node.right and path_sum == targetsum:
return True return true
if cur_node.right: if cur_node.right:
stack.append((cur_node.right, path_sum + cur_node.right.val)) stack.append((cur_node.right, path_sum + cur_node.right.val))
@ -471,20 +462,15 @@ class Solution:
if cur_node.left: if cur_node.left:
stack.append((cur_node.left, path_sum + cur_node.left.val)) stack.append((cur_node.left, path_sum + cur_node.left.val))
return False return false
``` ```
0113.路径总和-ii 0113.路径总和-ii
**递归** **递归**
```python ```python
# Definition for a binary tree node. class solution:
# class TreeNode: def pathsum(self, root: treenode, targetsum: int) -> list[list[int]]:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def pathSum(self, root: TreeNode, targetSum: int) -> List[List[int]]:
def traversal(cur_node, remain): def traversal(cur_node, remain):
if not cur_node.left and not cur_node.right and remain == 0: if not cur_node.left and not cur_node.right and remain == 0:
@ -511,109 +497,107 @@ class Solution:
if not root: if not root:
return [] return []
path.append(root.val) path.append(root.val)
traversal(root, targetSum - root.val) traversal(root, targetsum - root.val)
return result return result
``` ```
Go ## go
> 112. 路径总和 112. 路径总和
```go ```go
//递归法 //递归法
/** /**
* Definition for a binary tree node. * definition for a binary tree node.
* type TreeNode struct { * type treenode struct {
* Val int * val int
* Left *TreeNode * left *treenode
* Right *TreeNode * right *treenode
* } * }
*/ */
func hasPathSum(root *TreeNode, targetSum int) bool { func haspathsum(root *treenode, targetsum int) bool {
var flage bool //找没找到的标志 var flage bool //找没找到的标志
if root==nil{ if root==nil{
return flage return flage
} }
pathSum(root,0,targetSum,&flage) pathsum(root,0,targetsum,&flage)
return flage return flage
} }
func pathSum(root *TreeNode, sum int,targetSum int,flage *bool){ func pathsum(root *treenode, sum int,targetsum int,flage *bool){
sum+=root.Val sum+=root.val
if root.Left==nil&&root.Right==nil&&sum==targetSum{ if root.left==nil&&root.right==nil&&sum==targetsum{
*flage=true *flage=true
return return
} }
if root.Left!=nil&&!(*flage){//左节点不为空且还没找到 if root.left!=nil&&!(*flage){//左节点不为空且还没找到
pathSum(root.Left,sum,targetSum,flage) pathsum(root.left,sum,targetsum,flage)
} }
if root.Right!=nil&&!(*flage){//右节点不为空且没找到 if root.right!=nil&&!(*flage){//右节点不为空且没找到
pathSum(root.Right,sum,targetSum,flage) pathsum(root.right,sum,targetsum,flage)
} }
} }
``` ```
113 递归法
> 113 递归法
```go ```go
/** /**
* Definition for a binary tree node. * definition for a binary tree node.
* type TreeNode struct { * type treenode struct {
* Val int * val int
* Left *TreeNode * left *treenode
* Right *TreeNode * right *treenode
* } * }
*/ */
func pathSum(root *TreeNode, targetSum int) [][]int { func pathsum(root *treenode, targetsum int) [][]int {
var result [][]int//最终结果 var result [][]int//最终结果
if root==nil{ if root==nil{
return result return result
} }
var sumNodes []int//经过路径的节点集合 var sumnodes []int//经过路径的节点集合
hasPathSum(root,&sumNodes,targetSum,&result) haspathsum(root,&sumnodes,targetsum,&result)
return result return result
} }
func hasPathSum(root *TreeNode,sumNodes *[]int,targetSum int,result *[][]int){ func haspathsum(root *treenode,sumnodes *[]int,targetsum int,result *[][]int){
*sumNodes=append(*sumNodes,root.Val) *sumnodes=append(*sumnodes,root.val)
if root.Left==nil&&root.Right==nil{//叶子节点 if root.left==nil&&root.right==nil{//叶子节点
fmt.Println(*sumNodes) fmt.println(*sumnodes)
var sum int var sum int
var number int var number int
for k,v:=range *sumNodes{//求该路径节点的和 for k,v:=range *sumnodes{//求该路径节点的和
sum+=v sum+=v
number=k number=k
} }
tempNodes:=make([]int,number+1)//新的nodes接受指针里的值防止最终指针里的值发生变动导致最后的结果都是最后一个sumNodes的值 tempnodes:=make([]int,number+1)//新的nodes接受指针里的值防止最终指针里的值发生变动导致最后的结果都是最后一个sumnodes的值
for k,v:=range *sumNodes{ for k,v:=range *sumnodes{
tempNodes[k]=v tempnodes[k]=v
} }
if sum==targetSum{ if sum==targetsum{
*result=append(*result,tempNodes) *result=append(*result,tempnodes)
} }
} }
if root.Left!=nil{ if root.left!=nil{
hasPathSum(root.Left,sumNodes,targetSum,result) haspathsum(root.left,sumnodes,targetsum,result)
*sumNodes=(*sumNodes)[:len(*sumNodes)-1]//回溯 *sumnodes=(*sumnodes)[:len(*sumnodes)-1]//回溯
} }
if root.Right!=nil{ if root.right!=nil{
hasPathSum(root.Right,sumNodes,targetSum,result) haspathsum(root.right,sumnodes,targetsum,result)
*sumNodes=(*sumNodes)[:len(*sumNodes)-1]//回溯 *sumnodes=(*sumnodes)[:len(*sumnodes)-1]//回溯
} }
} }
``` ```
JavaScript ## javascript
0112.路径总和 0112.路径总和
```javascript ```javascript
/** /**
* @param {TreeNode} root * @param {treenode} root
* @param {number} targetSum * @param {number} targetsum
* @return {boolean} * @return {boolean}
*/ */
let hasPathSum = function (root, targetSum) { let haspathsum = function (root, targetsum) {
// 递归法 // 递归法
const traversal = (node, cnt) => { const traversal = (node, cnt) => {
// 遇到叶子节点并且计数为0 // 遇到叶子节点并且计数为0
@ -628,19 +612,19 @@ let hasPathSum = function (root, targetSum) {
return false; return false;
}; };
if (!root) return false; if (!root) return false;
return traversal(root, targetSum - root.val); return traversal(root, targetsum - root.val);
// 精简代码: // 精简代码:
// if (!root) return false; // if (!root) return false;
// if (!root.left && !root.right && targetSum === root.val) return true; // if (!root.left && !root.right && targetsum === root.val) return true;
// return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val); // return haspathsum(root.left, targetsum - root.val) || haspathsum(root.right, targetsum - root.val);
}; };
``` ```
0113.路径总和-ii 0113.路径总和-ii
```javascript ```javascript
let pathSum = function (root, targetSum) { let pathsum = function (root, targetsum) {
// 递归法 // 递归法
// 要遍历整个树找到所有路径,所以递归函数不需要返回值, 与112不同 // 要遍历整个树找到所有路径,所以递归函数不需要返回值, 与112不同
const res = []; const res = [];
@ -666,62 +650,29 @@ let pathSum = function (root, targetSum) {
return; return;
}; };
if (!root) return res; if (!root) return res;
travelsal(root, targetSum - root.val, [root.val]); // 把根节点放进路径 travelsal(root, targetsum - root.val, [root.val]); // 把根节点放进路径
return res; return res;
}; };
``` ```
113 路径总和 精简版
0112 路径总和
```javascript ```javascript
var hasPathSum = function(root, targetSum) { var pathsum = function(root, targetsum) {
//递归方法 //递归方法
// 1. 确定函数参数 let respath = [],curpath = [];
const traversal = function(node,count){
// 2. 确定终止条件
if(node.left===null&&node.right===null&&count===0){
return true;
}
if(node.left===null&&node.right===null){
return false;
}
//3. 单层递归逻辑
if(node.left){
if(traversal(node.left,count-node.left.val)){
return true;
}
}
if(node.right){
if(traversal(node.right,count-node.right.val)){
return true;
}
}
return false;
}
if(root===null){
return false;
}
return traversal(root,targetSum-root.val);
};
```
113 路径总和
```javascript
var pathSum = function(root, targetSum) {
//递归方法
let resPath = [],curPath = [];
// 1. 确定递归函数参数 // 1. 确定递归函数参数
const travelTree = function(node,count){ const traveltree = function(node,count){
curPath.push(node.val); curpath.push(node.val);
count-=node.val; count-=node.val;
if(node.left===null&&node.right===null&&count===0){ if(node.left===null&&node.right===null&&count===0){
resPath.push([...curPath]); respath.push([...curpath]);
} }
node.left&&travelTree(node.left,count); node.left&&traveltree(node.left,count);
node.right&&travelTree(node.right,count); node.right&&traveltree(node.right,count);
let cur = curPath.pop(); let cur = curpath.pop();
count-=cur; count-=cur;
} }
if(root===null){ if(root===null){
return resPath; return respath;
} }
travelTree(root,targetSum); travelTree(root,targetSum);
return resPath; return resPath;
@ -730,6 +681,7 @@ var pathSum = function(root, targetSum) {
----------------------- -----------------------
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw) * 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
* B站视频[代码随想录](https://space.bilibili.com/525438321) * B站视频[代码随想录](https://space.bilibili.com/525438321)