Count Complete Tree Nodes — Solution in Python, Java & C++
Count Complete Tree Nodes solution explained: step-by-step approach, complexity and code in Python, Java, C++ and JavaScript. An easy problem.
Count Complete Tree Nodes is an easy coding problem on binary search, trees and bit manipulation, asked in Amazon, Google and Microsoft interviews.
- Difficulty: Easy
- Topics: Binary Search, Trees, Bit Manipulation
- Asked at: Amazon, Google, Microsoft
- Time limit: 2 s
- Memory limit: 256 MB
- Languages: JavaScript, TypeScript, Python, Java, C++, C, C#, Go, Kotlin, Swift, Rust, PHP and Ruby
Problem statement
You are given the root of a complete binary tree: every level is completely filled except possibly the last, and the nodes of the last level are packed as far left as possible.
Return the number of nodes in the tree. Aim for an algorithm that runs in less than O(n) time.
Example 1
Input: root = [1,2,3,4,5,6]
Output: 6
Explanation: Two full levels plus three nodes on the last one.
Example 2
Input: root = []
Output: 0
Explanation: The empty tree has no nodes.
Example 3
Input: root = [1]
Output: 1
Explanation: Just the root.
Constraints
0 <= number of nodes <= 5 * 10^40 <= Node.val <= 5 * 10^4the tree is complete
Hints for Count Complete Tree Nodes
Hint 1
Counting every node is O(n). The completeness should let you skip whole subtrees.
Hint 2
Walk down the leftmost path and the rightmost path. If they are equally long, the tree is perfect and has
2^h - 1nodes.Hint 3
Otherwise count
1 + count(left) + count(right): at least one of the two subtrees is perfect and is answered by the height check at once.
How to solve Count Complete Tree Nodes
A perfect tree of height h has 2^h - 1 nodes, and checking whether a complete subtree is perfect costs only its height: compare the length of its leftmost path with the length of its rightmost path. Recursing only where the check fails touches O(log n) subtrees.
Approach
- If the node is null, return 0.
- Measure
lh, the number of nodes on the path that always goes left, andrh, the number on the path that always goes right. - If
lh == rh, the subtree is perfect: return2^lh - 1. - Otherwise return
1 + countNodes(left) + countNodes(right).
Why it works
In a complete tree, the leftmost path reaches the deepest level. If the rightmost path is just as long, the last level is full, so the tree is perfect. If not, the last level's boundary lies in one subtree: the other subtree is perfect and stops after one height check, so each level of the recursion does real work in only one subtree.
Complexity
- Time —
O(log² n) — O(log n) levels, each with O(log n) height walks - Space —
O(log n) for the recursion
Pitfalls
- Count heights in nodes, not edges, so a perfect tree of height
hhas2^h - 1nodes. - A plain traversal is accepted for correctness but misses what the problem is about.
Reference solution
Python
from typing import Optional
def countNodes(root: Optional[TreeNode]) -> int:
if root is None:
return 0
lh, node = 0, root
while node:
lh += 1
node = node.left
rh, node = 0, root
while node:
rh += 1
node = node.right
if lh == rh:
return (1 << lh) - 1
return 1 + countNodes(root.left) + countNodes(root.right)Java
public static int countNodes(TreeNode root) {
if (root == null) return 0;
int lh = 0, rh = 0;
for (TreeNode node = root; node != null; node = node.left) lh++;
for (TreeNode node = root; node != null; node = node.right) rh++;
if (lh == rh) return (1 << lh) - 1;
return 1 + countNodes(root.left) + countNodes(root.right);
}C++
int countNodes(TreeNode* root) {
if (!root) return 0;
int lh = 0, rh = 0;
for (TreeNode* node = root; node; node = node->left) lh++;
for (TreeNode* node = root; node; node = node->right) rh++;
if (lh == rh) return (1 << lh) - 1;
return 1 + countNodes(root->left) + countNodes(root->right);
}JavaScript
var countNodes = function(root) {
if (root === null) return 0;
var lh = 0, rh = 0, node;
for (node = root; node !== null; node = node.left) lh++;
for (node = root; node !== null; node = node.right) rh++;
if (lh === rh) return (1 << lh) - 1;
return 1 + countNodes(root.left) + countNodes(root.right);
};Also on the editorial tab: C, C#, Go, Kotlin, PHP, Ruby, Rust, Swift, TypeScript.
All 189 binary search problems · the whole catalogue
Learn the technique: Binary Search · Binary Trees and Tree Traversals