题目描述

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

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

示例 1:

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

示例 2:

1
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

解法

  • 前缀和+深度优先搜索
    • 记录下根节点 root到当前节点 p的路径上除当前节点以外所有节点的前缀和
    • 在已保存的路径前缀和中查找是否存在前缀和刚好等于当前节点到根节点的前缀和 currentSum减去 targetSum
      • 对于空路径我们也需要保存预先处理一下
      • 当我们退出当前节点时,我们需要及时更新已经保存的前缀和,不能让自底向上过程受到影响
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Solution {

public int pathSum(TreeNode root, int targetSum) {
//1.定义前缀和
Map<Long,Integer> prefix=new HashMap<>();
prefix.put(0L, 1);//长度为0的前缀和必定存在
return dfs(root, prefix, 0, targetSum);
}

/**
* 深度优先搜索
* @param node 当前节点
* @param prefix 前缀和集合 k:前缀和 v:当前前缀和的出现次数
* @param currentSum 前缀和加到现在的和
* @param targetSum 目标值
* @return
*/
public int dfs(TreeNode node, Map<Long,Integer> prefix,long currentSum,int targetSum){
//1.定义递归出口
if (node==null){
return 0;
}
//深度优先搜索
int res=0;
currentSum+=node.val;

//2.是否存在满足当前节点+前缀和=target的情况
res=prefix.getOrDefault(currentSum-targetSum, 0);
//3.将当前前缀和放入集合中
prefix.put(currentSum, prefix.getOrDefault(currentSum, 0)+1);
//4.左右子树遍历
res+=dfs(node.left, prefix, currentSum, targetSum);
res+=dfs(node.right, prefix, currentSum, targetSum);
//5.当前节点递归完成后 ,还原之前的情况,因为现在处于自底向上的情况
prefix.put(currentSum, prefix.getOrDefault(currentSum, 0)-1);

return res;
}
}
  • 时间复杂度:O(n)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
int cnt=0;
public int pathSum(TreeNode root, int targetSum) {
if (root==null){
return 0;
}
//真正的计算
rootSum(root,targetSum);
//枚举每个节点进行计算
pathSum(root.left,targetSum);
pathSum(root.right,targetSum);
return cnt;
}

private void rootSum(TreeNode root, long targetSum) {
if (root==null){
return;
}
int val=root.val;
if (val==targetSum){
cnt++;
}
rootSum(root.left, targetSum-val);
rootSum(root.right, targetSum-val);
}
}

来源:力扣(LeetCode)
链接:437. 路径总和 III - 力扣(LeetCode)