跳到主要内容

437. 路径总和 III

题目描述

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

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

示例 1

示例 1

输入root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8

输出3

解释:和等于 8 的路径有 3 条,如图所示。

示例 2

输入root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22

输出3

提示

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

出处LeetCode

解法一:递归

思路

对于每个节点,都有两种情况:

  1. 以当前节点为起点,向下寻找路径;
  2. 不以当前节点为起点,向下寻找路径。

因此,可以递归地计算以当前节点为起点的路径数目,然后递归地计算左右子树的路径数目。

实现

function pathSum(root: TreeNode | null, targetSum: number): number {
if (root === null) {
return 0;
}
return pathSumStartWithRoot(root, targetSum)
+ pathSum(root.left, targetSum)
+ pathSum(root.right, targetSum);
}

function pathSumStartWithRoot(root: TreeNode | null, targetSum: number): number {
if (root === null) return 0;
let count = 0;
if (root.val === targetSum) count++;
count += pathSumStartWithRoot(root.left, targetSum - root.val);
count += pathSumStartWithRoot(root.right, targetSum - root.val);
return count;
}

复杂度分析

  • 时间复杂度:O(n2)O(n^2),其中 n 是二叉树的节点个数。
  • 空间复杂度:O(n)O(n)

解法二:前缀和 + 回溯

思路

对于每个节点,可以计算从根节点到当前节点的路径和,然后计算从根节点到当前节点的路径和减去目标和的值是否在前缀和中出现过。

实现

function pathSum(root: TreeNode | null, targetSum: number): number {
const prefixSum = new Map<number, number>();
prefixSum.set(0, 1);
return pathSumStartWithRoot(root, targetSum, 0, prefixSum);
}

function pathSumStartWithRoot(
root: TreeNode | null,
targetSum: number,
currentSum: number,
prefixSum: Map<number, number>,
): number {
if (root === null) return 0;
let count = 0;
currentSum += root.val;
count += prefixSum.get(currentSum - targetSum) ?? 0;
prefixSum.set(currentSum, (prefixSum.get(currentSum) ?? 0) + 1);
count += pathSumStartWithRoot(root.left, targetSum, currentSum, prefixSum);
count += pathSumStartWithRoot(root.right, targetSum, currentSum, prefixSum);
prefixSum.set(currentSum, (prefixSum.get(currentSum) ?? 0) - 1);
return count;
}

复杂度分析

  • 时间复杂度:O(n)O(n),其中 n 是二叉树的节点个数。
  • 空间复杂度:O(n)O(n)