The number of nodes in the tree is in the range [0, 1000].
-109 <= Node.val <= 109
-1000 <= targetSum <= 1000
Solutions
Solution 1: Hash Table + Prefix Sum + Recursion
Thinking
Paths must go downward. Trying every ancestor then walking down is \(O(n^2)\). A path summing to \(\textit{targetSum}\) is a current prefix minus some ancestor prefix.
Accumulate the prefix \(s\) in preorder and store prefix frequencies on the root-to-node path. \(\textit{cnt}[s-\textit{targetSum}]\) counts valid paths ending here. Undo \(s\) on the way back so another branch does not see it.
\(\textit{cnt}[0]=1\) accounts for a path that starts at the root. Lookup before insert so the current node is not used twice.
We can use the idea of prefix sums to recursively traverse the binary tree while using a hash table \(\textit{cnt}\) to count the occurrences of each prefix sum along the path from the root to the current node.
We design a recursive function \(\textit{dfs(node, s)}\), where \(\textit{node}\) represents the current node being traversed, and \(s\) represents the prefix sum along the path from the root to the current node. The return value of the function is the number of paths ending at \(\textit{node}\) or its subtree nodes with a sum equal to \(\textit{targetSum}\). The final answer is \(\textit{dfs(root, 0)}\).
The recursive process of \(\textit{dfs(node, s)}\) is as follows:
If the current node \(\textit{node}\) is null, return \(0\).
Calculate the prefix sum \(s\) along the path from the root to the current node.
Use \(\textit{cnt}[s - \textit{targetSum}]\) to represent the number of paths ending at the current node with a sum equal to \(\textit{targetSum}\). Here, \(\textit{cnt}[s - \textit{targetSum}]\) is the count of prefix sums equal to \(s - \textit{targetSum}\) in \(\textit{cnt}\).
Increment the count of the prefix sum \(s\) by \(1\), i.e., \(\textit{cnt}[s] = \textit{cnt}[s] + 1\).
Recursively traverse the left and right child nodes of the current node by calling \(\textit{dfs(node.left, s)}\) and \(\textit{dfs(node.right, s)}\), and add their return values.
After the return value is calculated, decrement the count of the prefix sum \(s\) by \(1\), i.e., \(\textit{cnt}[s] = \textit{cnt}[s] - 1\).
Finally, return the result.
The time complexity is \(O(n)\), and the space complexity is \(O(n)\), where \(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],targetSum:int)->int:defdfs(node,s):ifnodeisNone:return0s+=node.valans=cnt[s-targetSum]cnt[s]+=1ans+=dfs(node.left,s)ans+=dfs(node.right,s)cnt[s]-=1returnanscnt=Counter({0:1})returndfs(root,0)
/** * Definition for a binary tree node. * type TreeNode struct { * Val int * Left *TreeNode * Right *TreeNode * } */funcpathSum(root*TreeNode,targetSumint)int{cnt:=map[int]int{0:1}vardfsfunc(*TreeNode,int)intdfs=func(node*TreeNode,sint)int{ifnode==nil{return0}s+=node.Valans:=cnt[s-targetSum]cnt[s]++ans+=dfs(node.Left,s)+dfs(node.Right,s)cnt[s]--returnans}returndfs(root,0)}