【阿秋学算法】113. 路径总和 II

32 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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 算法是在遍历「节点」

回溯算法框架:

  1. 路径:也就是已经做出的选择。
  2. 选择列表:也就是你当前可以做的选择。
  3. 结束条件:也就是到达决策树底层,无法再做选择的条件。

其核心就是 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;
}