437. Path Sum III (top-to-down, find path for target)
You are given a binary tree in which each node contains an integer value.
Find 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).
The tree has no more than 1,000 nodes and the values are in the range -1,000,000 to 1,000,000.
Example:
root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8
10
/ \
5 -3
/\ \
3 2 11
/ \ \
3 -2 1
Return 3. The paths that sum to 8 are:
1. 5 -> 3
2. 5 -> 2 -> 1
3. -3 -> 11
Thoughts:
DFS recursion: T: O(N^2)
- Find the root.left and root.right: (base case: for root == null; return 0)
- if (both left and right ==0)-> leaf node, then return 1,
- if only left == 0: have to return right + 1
- if only right == 0; have to return left + 1
- if both left and right != 0; then return the min(left,right) + 1
- Merge sort : T: T(N) = N + 2T(N/2) = O(NlogN) or O(N^2) for worse complexity (unbalanced tree)
Two Sum Method: Hash table: T: O(n) S: O(n):
- As we traverse down the tree, at an arbitrary node N, we store the sum until this node N (sum_so_far (prefix) + N.val). in hash-table. Note this sum is the sum from root to N.
- Now at a grand-child of N, say G, we can compute the sum from the root until G since we have the prefix_sum until this grandchild available.We pass in our recursive routine.
- Search for prefixSum + node.val - target for the predecessor
- Once done with a node and all its grandchildren, we remove it from the hash-table. This makes sure that the number of complement paths returned always correspond to paths that ended(started) at a predecessor node.
Code: DFS Recursion O(N^2)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public int pathSum(TreeNode root, int sum) {
if(root == null) return 0;
int left = pathSum(root.left, sum);
int right = pathSum(root.right, sum);
return left + right + pathSumStart(root, sum);
// wrong:
// int left = pathSum(root.left, sum) + pathSum(root.left, sum - root.val);
// int right = pathSum(root.right, sum) + pathSum(root.right, sum - root.val);
// System.out.println(root.val + " " + sum + " " + left + " " + right );
// return left + right + (root.val == sum ?1:0);
}
private int pathSumStart(TreeNode node, int sum){
if(node == null) return 0;
return (node.val == sum ?1:0)
+ pathSumStart(node.left, sum - node.val)
+ pathSumStart(node.right, sum - node.val);
}
}
Code: Python
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def find_paths(self, root, sum):
"""
:type root: TreeNode
:type sum: int
:rtype: int
"""
if root:
return int(root.val == sum) + self.find_paths(root.left, sum - root.val) + self.find_paths(root.right, sum - root.val)
return 0
def pathSum(self, root, sum):
if root:
return self.find_paths(root, sum) + self.pathSum(root.left, sum) + self.pathSum(root.right, sum)
return 0
Code: Two-Sum: HashTable: T: O(n) S: O(n)
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def helper(self,root, target, preS, path):
if root:
key = preS + root.val - target
if key in path:
self.result += path[key]
path.setdefault(preS + root.val, 0) # if not found, set to 0
path[preS + root.val] +=1
self.helper(root.left, target, preS+root.val, path)
self.helper(root.right, target, preS+root.val, path)
# remove predecessor from the record
path[preS + root.val] -=1
return
def pathSum(self, root, sum):
"""
:type root: TreeNode
:type sum: int
:rtype: int
"""
self.result = 0
self.helper(root,sum,0, {0:1})
return self.result