Reference: LeetCode
Difficulty: Medium
Problem
We are given the head node
rootof a binary tree, where additionally every node’s value is either a0or a1. Return the same tree where every subtree (of the given tree) not containing a1has been removed.
Recall that the subtree of a node
XisX, plus every node that is a descendant ofX.
Note:
- The binary tree will have at most
100 nodes. - The value of each node will only be
0or1.
Example:
1 | Example 1: |
![]()
1 | Example 2: |
![]()
Analysis
Methods:
- Recursion
- Prune children of the tree recursively. The only decision at each node is whether to prune the left child or the right child or not.
containsOne(node): Whether the tree at thisnodecontains1, and it also prunes all subtrees not containing1, e.g.node.leftdoes not contain a1, then we should prune it vianode.left = null.- Also, the current node’s value needs to be checked.
- Time: $O(N)$
- Space: $O(h)$
Code
Recursion
Bad Code
Note:
- This is the first version I wrote, but it turns out that
containsOne(node)does a lot of repeated jobs. - To improve, consider the traversal order. We can put the
line 1after visiting left subtree and right subtree. Therefore, traversal order sometimes is very important in performance or in reducing repeated calculations.
1 | public TreeNode pruneTree(TreeNode root) { |
Change pruneTree to:
1 | return containsOne(root) ? root : null; |
Change the line 1 & 2 to:
1 | boolean l = containsOne(root.left); // do it first! |
I try using a HashMap to cache those calculated nodes, but the runtime does not improve and even get worse.
1 | public TreeNode pruneTree(TreeNode root) { |
Clean Code
Note:
- Can we do pruning in
containsOne(node)? - It is a
postordertraversal. Can we do it inpreorderway, which means checking the current node first? No! Ifroot.val == 1, we cannot just returntrue, since we need to check the children. - If
rootisnull, we should returnfalse. List all the base cases to see why it is the case.
1 | public TreeNode pruneTree(TreeNode root) { |