这道题原来可以用到 JS 这么多知识点!
✨文章摘要(AI生成)
在这篇文章中,笔者探讨了如何解决“二叉树中和为某一值的路径”这一问题。题目要求从二叉树的根节点到叶子节点的路径,其节点值之和需等于给定的 expectNumber
。为了解决此题,笔者采用了深度优先遍历(DFS)的策略,利用递归来遍历树的每一条路径。
笔者特别强调了两种变量的区别:值变量 cur
和引用变量 arr
。cur
用于存储当前的累加和,而 arr
则用于存储当前路径。为了避免在递归中对 arr
的修改影响到外部作用域,笔者使用了 ES6 的扩展运算符来复制数组。最终,笔者给出了清晰的代码实现,并附上了注释,确保读者能够理解每一步的逻辑和实现细节。
JZ34 二叉树中和为某一值的路径(二)
题目描述
输入一颗二叉树的根节点 root 和一个整数 expectNumber,找出二叉树中结点值的和为 expectNumber 的所有路径。
- 该题路径定义为从树的根结点开始往下一直到叶子结点所经过的结点
- 叶子节点是指没有子节点的节点
- 路径只能从父节点到子节点,不能从子节点到父节点
- 总节点数目为 n
输入:{10,5,12,4,7},22
返回值:[[10,5,7],[10,12]]
说明:返回[[10,12],[10,5,7]]也是对的
function TreeNode(x) {
this.val = x;
this.left = null;
this.right = null;
}
我的解法
在解这道题时,题目中有两点值得注意:
- 要求的是根到叶子节点
- 和为给定数
显然,这是一道深度优先遍历出所有满足条件的路径
这里,我使用了cur
来存储当前的累加和,使用了arr
来存储当前的路径信息;
这两个的区别就是我们今天的重点:
cur
为值变量,它是保存在栈之中的,作为参数传入函数中,函数修改了该值也不会对当前作用域的cur
造成影响;- javascript
{ let cur = 0; ((cur)=>{cur = 1})(cur); console.log(cur); // 1; }
arr
作为引用变量,它是保存在堆里面,作为参数传入函数中时,它是传入的指针,所以修改的值也会影响到所有指向该对象的指针,这个对象此时只有一个;- javascript
{ const arr = [1,2,3]; ((arr)=>{arr.push(4)})(arr); console.log(arr); // [ 1, 2, 3, 4 ] }
所以我们要想arr
在函数中修改不会影响到外部作用域,可以将其复制,然后再传入函数中,这时候对象就有两个了;
{
const arr = [1,2,3];
((arr)=>{arr.push(4)})([...arr]); // 这里使用 ES6 的语法进行复制
console.log(arr); // [ 1, 2, 3 ]
}
然后我们将其结合递归,递归其实也是内部有一个自己的函数,然后就是需要注意一下结束条件是如何返回的,下面就是该题的解法,该注释都注释了,如有问题请在评论区提出:
// 题解
function FindPath(root, expectNumber){
let res = []; // 存储符合该题条件的路径
(function Dfs(root, cur, arr){
if(!root) return; // root 为空时
cur += root.val; // 加上当前节点的值
arr.push(root.val); // 保存当前节点
if(!root.left && !root.right && cur === expectNumber){
res.push(arr); // 符合条件的路径
}
Dfs(root.left, cur, [...arr]); // 遍历左子树
Dfs(root.right, cur, [...arr]); // 遍历右子树
})(root, 0, []);
return res;
}
当存储函数栈帧时,cur 和 arr 会在之前的情况下添加节点,当弹出栈帧时,cur 和 arr 会在之前的情况减少一个节点,因为返回到上一作用域了。