leetcode hot100之路径总和 III(437)解析

150 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第21天,点击查看活动详情


前言

  • leetcode hot100,是大厂面试高频题,也是必刷算法题。精选了100道LeetCode上最热门的题目,适合初识算法与数据结构的新手和想要在短时间内高效提升的人,按照官方说的,熟练掌握这 100 道题,就具备了代码世界通行的基本能力。

leetcode437题(路径总和 III

本文来讲hot100第437题,路径总和,本题题目是中等题目,也是典型的前缀和应用,与560题很像。

给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。

路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。

微信截图_20220817224122.png

示例:

输入:root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
输出:3
解释:和等于 8 的路径有 3 条,如图所示。
输入: root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出: 3

提示:

  • 二叉树的节点个数的范围是 [0,1000]
  • -109 <= Node.val <= 109 
  • -1000 <= targetSum <= 1000

分析

  1. 求二叉树里节点值之和等于targetSum的路径的数目,简单的来说就是看整个树上有多少条“路径”的和等于targetSum
  2. 从下面的例图也可以看出来,“路径”的方向是向下的,可以左节点也可以右节点。

思路

暴力法

  • 求所有从根节点到叶子节点的路径,存储下来,然后我们再针对每条路径双指针匹配路径等于targetSum的区间。时间复杂度很高,很可能会超时

前缀和

  • 看到路径会想起来之前我们560题(和为k的子数组)讲过前缀和,前缀和是从第0项到当前位置的数(nums[i])的和,也是在数组中求路径和的应用。
    1. 前缀和对于本题的作用,题目要求的是找出路径和等于给定数值的路径总数, 而:两节点间的路径和 = 两节点的前缀和之差
    2. 理解了第一点路径和之差,可以考虑2点
      • 存储key是“键为presum的前缀和”,value是“键为presum的前缀和”的值,这里我们加一
      • 考虑到边界情况和后续的迭代,初始化前缀和是{0:1}
    3. 由于路径是向下的,所以是先左子节点 再判断右子节点

代码

let ans = 0, map = new Map()
const dfs = (node, presum = 0) => {
  if (!node) {
      return 0
  }
  map.set(presum, (map.get(presum) || 0 ) + 1)
  // 当前前缀和为之前的前缀和加当前的节点值
  const target = presum + node.val
  // 查找匹配的前缀和数量并加到ans
  ans += (map.get(target-targetSum) || 0)
  dfs(node.left, target)
  dfs(node.right, target)
  // 回溯,撤销
  map.set(presum, map.get(presum) - 1)

}
dfs(root)
return ans;

结语

  • 本题也是前缀和的应用,只要理解了前缀和的公式还有为什么我们匹配target - targetSum对应的前缀和,就可以很容易的做出来了,做完此题可以去做560题。