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
Solutions
Solution 1: Hash Table + Prefix Sum + Recursion
We can use the idea of prefix sum to recursively traverse the binary tree, and use a hash table \(cnt\) to count the occurrence of each prefix sum on the path from the root node to the current node.
We design a recursive function \(dfs(node, s)\), where the current node being traversed is \(node\), and the prefix sum on the path from the root node to the current node is \(s\). The return value of the function is the number of paths with the path sum equal to \(sum\) and the path ends at the \(node\) node or its subtree nodes. Therefore, the answer is \(dfs(root, 0)\).
The recursive process of the function \(dfs(node, s)\) is as follows:
If the current node \(node\) is null, return \(0\).
Calculate the prefix sum \(s\) on the path from the root node to the current node.
Use \(cnt[s - sum]\) to represent the number of paths with the path sum equal to \(sum\) and the path ends at the current node, where \(cnt[s - sum]\) is the count of the prefix sum equal to \(s - sum\) in \(cnt\).
Add the count of the prefix sum \(s\) by \(1\), i.e., \(cnt[s] = cnt[s] + 1\).
Recursively traverse the left and right child nodes of the current node, i.e., call the functions \(dfs(node.left, s)\) and \(dfs(node.right, s)\), and add their return values.
After the return value is calculated, subtract the count of the prefix sum \(s\) of the current node by \(1\), i.e., execute \(cnt[s] = cnt[s] - 1\).
Finally, return the answer.
The time complexity is \(O(n)\), and the space complexity is \(O(n)\). Here, \(n\) is the number of nodes in the binary tree.
1 2 3 4 5 6 7 8 9101112131415161718192021
# Definition for a binary tree node.# class TreeNode:# def __init__(self, val=0, left=None, right=None):# self.val = val# self.left = left# self.right = rightclassSolution:defpathSum(self,root:Optional[TreeNode],sum:int)->int:defdfs(root:Optional[TreeNode],s:int)->int:ifrootisNone:return0s+=root.valans=cnt[s-sum]cnt[s]+=1ans+=dfs(root.left,s)ans+=dfs(root.right,s)cnt[s]-=1returnanscnt=Counter({0:1})returndfs(root,0)
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */classSolution{privateMap<Long,Integer>cnt=newHashMap<>();privateinttarget;publicintpathSum(TreeNoderoot,intsum){cnt.put(0L,1);target=sum;returndfs(root,0);}privateintdfs(TreeNoderoot,longs){if(root==null){return0;}s+=root.val;intans=cnt.getOrDefault(s-target,0);cnt.merge(s,1,Integer::sum);ans+=dfs(root.left,s);ans+=dfs(root.right,s);cnt.merge(s,-1,Integer::sum);returnans;}}
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */classSolution{public:intpathSum(TreeNode*root,intsum){unordered_map<longlong,int>cnt{{0,1}};autodfs=[&](thisauto&&dfs,TreeNode*root,longlongs)->int{if(!root){return0;}s+=root->val;intans=cnt[s-sum];++cnt[s];ans+=dfs(root->left,s);ans+=dfs(root->right,s);--cnt[s];returnans;};returndfs(root,0);}};
1 2 3 4 5 6 7 8 910111213141516171819202122232425
/** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */funcpathSum(root*TreeNode,sumint)int{cnt:=map[int]int{0:1}vardfsfunc(*TreeNode,int)intdfs=func(root*TreeNode,sint)int{ifroot==nil{return0}s+=root.Valans:=cnt[s-sum]cnt[s]++ans+=dfs(root.Left,s)ans+=dfs(root.Right,s)cnt[s]--returnans}returndfs(root,0)}
/** * Definition for a binary tree node. * public class TreeNode { * public var val: Int * public var left: TreeNode? * public var right: TreeNode? * public init() { self.val = 0; self.left = nil; self.right = nil; } * public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } * public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { * self.val = val * self.left = left * self.right = right * } * } */classSolution{funcpathSum(_root:TreeNode?,_sum:Int)->Int{varcnt:[Int:Int]=[0:1]funcdfs(_root:TreeNode?,_s:Int)->Int{guardletroot=rootelse{return0}vars=s+root.valvarans=cnt[s-sum,default:0]cnt[s,default:0]+=1ans+=dfs(root.left,s)ans+=dfs(root.right,s)cnt[s,default:0]-=1returnans}returndfs(root,0)}}