持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情
题目描述
113. 路径总和 II
难度 中等
给你二叉树的根节点 root
和一个整数目标和 targetSum
,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
叶子节点 是指没有子节点的节点。
示例 1:
输入: root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出: [[5,4,11,2],[5,8,4,5]]
示例 2:
输入: root = [1,2,3], targetSum = 5
输出: []
示例 3:
输入: root = [1,2], targetSum = 0
输出: []
提示:
- 树中节点总数在范围
[0, 5000]
内 -1000 <= Node.val <= 1000
-1000 <= targetSum <= 1000
解析
图遍历。在遍历前,先将数据入栈,遍历完后进行出栈。
只要遍历一遍二叉树,就可以把所有符合条件的路径找出来。为了维护经过的路径,在进入递归的时候要在 path
列表添加节点,结束递归的时候删除节点,类似 回溯算法。
其实回溯算法和我们常说的 DFS 算法非常类似,本质上就是一种暴力穷举算法。回溯算法和 DFS 算法的细微差别是:回溯算法是在遍历「树枝」,DFS 算法是在遍历「节点」
回溯算法框架:
- 路径:也就是已经做出的选择。
- 选择列表:也就是你当前可以做的选择。
- 结束条件:也就是到达决策树底层,无法再做选择的条件。
其核心就是 for 循环里面的递归,在递归调用之前「做选择」,在递归调用之后「撤销选择」
function pathSum(root, targetSum) {
const res = [];
const dfs = (root, sum, path) => {
if (!root) return null;
const remain = sum - root.val;
if (!root.left && !root.right) {
// 结束条件
if (remain === 0) {
res.push([...path, root.val]);
}
return;
}
// 做选择
path.push(root.val);
dfs(root.left, remain, path);
dfs(root.right, remain, path);
// 撤销选择
path.pop();
return root;
};
dfs(root, targetSum, []);
return res;
}