给定一个二叉树的根节点 root
,和一个整数 targetSum
,求该二叉树里节点值之和等于 targetSum
的 路径 的数目。
路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
//抄的
class Solution {
public:
int pathSum(TreeNode* root, int targetSum) {
unordered_map<long long, int> prefixSumCount;
prefixSumCount[0] = 1;
return helper(root, 0, targetSum, prefixSumCount);
}
private:
int helper(TreeNode* node, long long currentSum, int targetSum, unordered_map<long long, int>& prefixSumCount) {
if (!node) {
return 0;
}
currentSum += node->val;
int res = prefixSumCount[currentSum - targetSum];
prefixSumCount[currentSum]++;
res += helper(node->left, currentSum, targetSum, prefixSumCount);
res += helper(node->right, currentSum, targetSum, prefixSumCount);
prefixSumCount[currentSum]--;
return res;
}
};
前缀和与哈希表结合,递归沿用之前路径总和的题目逻辑
前缀和是指从根节点到当前节点的路径上所有节点值的和。
利用前缀和可以快速计算任意子路径的和:子路径和 = 当前前缀和 - 历史前缀和
。
使用哈希表 prefixSumCount
记录遍历过程中所有前缀和的出现次数。通过检查 currentSum - targetSum
是否在哈希表中,直接得到以当前节点为终点的满足条件的路径数目。
主要逻辑如下
prefixSumCount[0] = 1
:表示前缀和为 0
的路径初始出现一次(空路径)
终止条件:当前节点为空时返回 0
。
计算当前前缀和:currentSum += node->val
。
统计满足条件的路径:res = prefixSumCount[currentSum - targetSum]
。如果 currentSum - targetSum
存在于哈希表中,说明存在一个历史前缀和,使得两者之差为 targetSum
,即找到一条路径。
更新哈希表:prefixSumCount[currentSum]++
,记录当前前缀和。
递归左右子树:继续搜索以当前节点为起点的路径。
回溯:prefixSumCount[currentSum]--
,确保递归返回时哈希表状态正确(避免干扰其他分支的统计)。