求和路径
难度:
标签:
题目描述
You are given a binary tree in which each node contains an integer value (which might be positive or negative). Design an algorithm to count the number of paths that sum to a given value. The path does not need to start or end at the root or a leaf, but it must go downwards (traveling only from parent nodes to child nodes).
Example:
Given the following tree and sum = 22,
5 / \ 4 8 / / \ 11 13 4 / \ / \ 7 2 5 1
Output:
3 Explanation: Paths that have sum 22 are: [5,4,11,2], [5,8,4,5], [4,11,7]
Note:
node number <= 10000
代码结果
运行时间: 30 ms, 内存: 17.0 MB
/*
* 思路:
* 1. 将树的所有路径转换为列表,并在每条路径中查找目标和。
* 2. 使用递归方法获取从当前节点开始的所有路径。
* 3. 使用Stream API计算每条路径的和,并过滤出等于目标和的路径。
* 4. 返回符合条件的路径数量。
*/
import java.util.*;
import java.util.stream.*;
public class PathSumIIIStream {
public int pathSum(TreeNode root, int sum) {
if (root == null) return 0;
List<List<Integer>> allPaths = getAllPaths(root);
return (int) allPaths.stream()
.flatMap(Collection::stream)
.filter(path -> path.stream().mapToInt(Integer::intValue).sum() == sum)
.count();
}
private List<List<Integer>> getAllPaths(TreeNode node) {
if (node == null) return Collections.emptyList();
List<List<Integer>> paths = new ArrayList<>();
if (node.left == null && node.right == null) {
paths.add(new ArrayList<>(Collections.singletonList(node.val)));
return paths;
}
for (List<Integer> path : getAllPaths(node.left)) {
path.add(0, node.val);
paths.add(path);
}
for (List<Integer> path : getAllPaths(node.right)) {
path.add(0, node.val);
paths.add(path);
}
return paths;
}
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
解释
方法:
该题解采用了前缀和的方法来高效地计算路径和。对于二叉树中的任意一条路径,可以通过维护一个从根节点到当前节点的路径和,以及一个哈希表来记录所有可能的前缀和及其出现的次数。对每个节点,计算当前的路径和,并查询哈希表中路径和减去目标值(sum)的结果出现的次数,这些次数即为以当前节点结束的、和为目标值的路径数量。在遍历每个节点后,更新哈希表以包含当前路径和的次数,并在返回前减少当前路径和的计数,以防影响其他路径的计算。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
为什么在哈希表中初始需要设置prefix[0]=1?这代表了什么含义?
▷🦆
在函数path中,prefix[total-sum]的查询是如何确保找到的路径是向下且不跨越非父子节点的?
▷🦆
在递归函数path中,对prefix的更新操作为何在递归调用前后都有执行,这种操作的目的是什么?
▷