Given a complete binary tree, count the number of nodes.
Note:
Definition of a complete binary tree from Wikipedia:
In a complete binary tree every level, except possibly the last, is completely filled, and all nodes in the last level are as far left as possible. It can have between 1 and 2h nodes inclusive at the last level h.
Example:
compare the depth between left sub tree and right sub tree.
A, If it is equal, it means the left sub tree is a full binary tree
B, It it is not , it means the right sub tree is a full binary tree
Intuition
Approach 1 doesn't profit from the fact that the tree is a complete one.
In a complete binary tree every level, except possibly the last, is completely filled, and all nodes in the last level are as far left as possible.
That means that complete tree has 2^k2k nodes in the kth level if the kth level is not the last one. The last level may be not filled completely, and hence in the last level the number of nodes could vary from 1 to 2^d2d, where d is a tree depth.
Now one could compute the number of nodes in all levels but the last one: \sum_{k = 0}^{k = d - 1}{2^k} = 2^d - 1∑k=0k=d−12k=2d−1. That reduces the problem to the simple check of how many nodes the tree has in the last level.
Now there are two questions:
Let's start from the first question. It's a complete tree, and hence all nodes in the last level are as far left as possible. That means that instead of checking the existence of all 2^d2d possible leafs, one could use binary search and check \log(2^d) = dlog(2d)=d leafs only.
Let's move to the second question, and enumerate potential nodes in the last level from 0 to 2^d - 12d−1. How to check if the node number idx exists? Let's use binary search again to reconstruct the sequence of moves from root to idx node. For example, idx = 4. idx is in the second half of nodes 0,1,2,3,4,5,6,7
and hence the first move is to the right. Then idx is in the first half of nodes 4,5,6,7
and hence the second move is to the left. The idx is in the first half of nodes 4,5
and hence the next move is to the left. The time complexity for one check is \mathcal{O}(d)O(d).
1 and 2 together result in \mathcal{O}(d)O(d) checks, each check at a price of \mathcal{O}(d)O(d). That means that the overall time complexity would be \mathcal{O}(d^2)O(d2).
Algorithm
d
.d == 0
.exists(idx, d, root)
to check if the node with index idx exists.exists(idx, d, root)
as well.Implementation
Complexity Analysis