Given a binary tree and a sum, find all root-to-leaf paths where each path’s sum equals the given sum.
The idea of this is to push all the left subtree nodes in the stack. then check if the leftest node has a right child if it has, we will go through all its right children tree nodes until the leaf node. The trick one is where to push the right node and where to delete them.
Approach1:Iterative DFS
class Solution {
public List<List<Integer>> pathSum(TreeNode root, int sum) {
List<List<Integer>> list = new ArrayList<>();
if (root == null) return list;
List<Integer> path = new ArrayList<>();
Stack<TreeNode> s = new Stack<>();
// sum along the current path
int pathSum = 0;
TreeNode prev = null;
TreeNode curr = root;
while (curr != null || !s.isEmpty()){
// go down all the way to the left leaf node
// add all the left nodes to the stack
while (curr != null){
s.push(curr);
// record the current path
path.add(curr.val);
// record the current sum along the current path
pathSum += curr.val;
curr = curr.left;
}
// check left leaf node's right subtree
// or check if it is not from the right subtree
// why peek here?
// because if it has right subtree, we don't need to push it back
// if we push it here, we will get an infinite loop.
// here we need to pay attention to the pre check condition
// 3
// \
// 4
// \
// 5
// suppose we have this kind of right subtree, we will push 3,4 and 5 to our stack.
//when we finish checking if the path to leaf 5 is a valid path, we will pop it.
// and the s.peak() will be 4, if we don't check the curr.right != pre we will push the
// right child of 4 to our stack and goes on and goes on. another infinite loop.
curr = s.peek();
if (curr.right != null && curr.right != prev){
curr = curr.right;
continue; // back to the outer while loop
}
// check leaf
if (curr.left == null && curr.right == null && pathSum == sum){
list.add(new ArrayList<Integer>(path));
// why do we need new arraylist here?
// if we are using the same path variable path
// path will be cleared after the traversal
}
// pop out the current value
s.pop();
prev = curr;
// subtract current node's val from path sum
pathSum -= curr.val;
// as this current node is done, remove it from the current path
path.remove(path.size()-1);
// reset current node to null, so check the next item from the stack
curr = null;//will not go back to add left nodes, this time will only check the
// possible "right" solution.
}
return list;
}
}
Approach1:Recursive solution
we use a helper DFS to get our solution recursively.
class Solution {
public List<List<Integer>> pathSum(TreeNode root, int sum) {
if(root == null) return new ArrayList();
List<Integer> path = new ArrayList<>();
List<List<Integer>> res = new ArrayList<>();
dfs(sum,0,path,root,res);
return res;
}
public void dfs(int target,int sum,List<Integer> path,TreeNode root, List<List<Integer>> res){
if(root == null) return;
sum += root.val;
path.add(root.val);
//check possible solution and add it.
if(target == sum && root.left == null && root.right == null){
res.add(new ArrayList(path));
}
if(root.left != null){
dfs(target,sum,path,root.left,res);//recursive call and we will update the root to root.left
path.remove(path.size() - 1);//delete the very last element of the path after each recursive call.
}
if(root.right != null){
dfs(target,sum,path,root.right,res);//same idea here
path.remove(path.size() - 1);
}
}
}