Binary Trees · 22 of 35
Check if Binary tree is Sum tree or not
Check that every parent in a tree holds exactly the total of everything below it, by adding up totals from the bottom.
- Simple way
- time O(n^2)
room O(h) - Clever way
- time O(n)
room O(h)
The problem, simply
You get a binary tree of numbers. It is a sum tree if every node that has children holds exactly the total of all the nodes in its left subtree plus all the nodes in its right subtree. Leaves are fine on their own, and an empty side counts as 0.
Answer true if the whole tree is a sum tree.
A story to remember it
Picture it
10 holds 4 + 6. The 3 in the middle row holds 0 + 3, because its left side is empty. The root 26 holds (10 + 4 + 6) + (3 + 3) = 20 + 6.
Examples
A sum tree
- In
[26, 10, 3, 4, 6, null, 3]- Out
true
Every parent holds the total of everything below it.
Only the root is wrong
- In
[10, 20, 30, 10, 10]- Out
false
20 holds 10 + 10, which is fine. But the root would need 20 + 10 + 10 + 30 = 70, and it holds 10.
Negative numbers
- In
[0, -1, 1]- Out
true
-1 + 1 = 0, so the root is right. This case breaks code that uses -1 to mean "not a sum tree".
One node
- In
[5]- Out
true
A leaf is always fine.
Empty tree
- In
[]- Out
true
Nothing to break.
Way 1: the simple way
At every node with children, add up its whole left subtree and its whole right subtree from scratch, and compare. Then check both children the same way.
- An empty node or a leaf is fine.
- Compute
total(left)andtotal(right)by walking those subtrees. - The node must equal their sum, and both children must pass too.
class Solution {
public boolean isSumTree(TreeNode root) {
if (root == null) return true;
if (root.left == null && root.right == null) return true; // a leaf is fine
int left = total(root.left);
int right = total(root.right);
return root.val == left + right && isSumTree(root.left) && isSumTree(root.right);
}
private int total(TreeNode n) {
if (n == null) return 0;
return n.val + total(n.left) + total(n.right);
}
}How long it takes: every node adds up everything below it again. In a stick shaped tree that is about n * n / 2 steps, O(n^2). Extra room: the waiting helpers, O(h).
Way 2: the clever way
Add up totals once, from the bottom up. Each helper returns the total of its whole subtree, and checks its own label on the way.
- An empty node returns 0.
- A leaf returns its value.
- Otherwise get
lfrom the left andrfrom the right. If the node is not equal tol + r, remember that the answer isfalse. - Return
node + l + rso the parent can use it.
Totals travel up, each parent checks its label
01 / 08
Each helper returns the total of everything in its subtree. Leaves are fine on their own. A node with children must equal the total of its left side plus its right side.
- ok
- true
- looking now
- done
- answer
class Solution {
private boolean ok;
public boolean isSumTree(TreeNode root) {
ok = true;
total(root);
return ok;
}
// returns the total of every node in this subtree
private int total(TreeNode n) {
if (n == null || !ok) return 0;
if (n.left == null && n.right == null) return n.val; // a leaf
int l = total(n.left);
int r = total(n.right);
if (n.val != l + r) ok = false; // wrong label
return n.val + l + r;
}
}How long it takes: each node is visited once, O(n). Extra room: the waiting helpers, O(h).
Watch out for
- Comparing only with the children's values. The label must equal the whole subtree, not just the two children. In the first example 26 is not 10 + 3.
- Treating a leaf as wrong because it is not 0 + 0. Leaves are fine by definition.
- Big totals can overflow
int. Uselongif the values are large.
What interviewers ask next
- Why does a passing node always return twice its value? Because its total is
node + l + randl + requalsnode. Some solutions return2 * nodefor that reason. - Turn any tree into a sum tree? Replace each node with the total of its subtrees, from the bottom up. That is the "convert to sum tree" problem.
- Count how many subtrees are sum trees? Return both the total and a flag from each helper, and count the flags.
Remember this
Grown-up words: the piggy bank labels are node values, the totals are subtree sums, children before parents is post order traversal, and the -1 trick is a sentinel value.