Count Complete Tree Nodes

Count Complete Tree Nodes Leetcode 222. Count Complete Tree Nodes

Count Complete Tree Nodes

Given the root of a complete binary tree, return the number of the nodes in the tree. According to Wikipedia, every level, except possibly the last, is completely filled in a complete binary tree, 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. Design an algorithm that runs in less than O(n) time complexity.

Approach 1:


class Solution {
    public int countNodes(TreeNode root) {
        return root != null ? 1 + countNodes(root.right) + countNodes(root.left) : 0;
    }
}
                

Time Complexity: O(n) and Space Complexity: O(n)


The problem Count Complete Tree Nodes requires counting the number of nodes in a complete binary tree. A complete binary tree is a binary tree in which every level, except possibly the last, is completely filled, and all nodes are as far left as possible.

Problem Statement

Given the root of a complete binary tree, you need to return the total number of nodes in the tree.

Approach to Solve the Problem

A complete binary tree is defined as a binary tree where all levels except possibly the last are completely filled. The nodes in the last level are as left as possible. To count the nodes in such a tree efficiently, we can take advantage of its special properties.

A naive approach would be to perform a depth-first search (DFS) or breadth-first search (BFS) traversal to count all nodes, but that would be inefficient. A better approach uses the structure of the complete binary tree to reduce the time complexity.

Optimal Approach:

The most efficient way to solve this problem is to use the fact that a complete binary tree is almost like a perfect binary tree except possibly at the last level. To count the nodes, we can perform a binary search-like approach to calculate the height of the tree and count nodes more effectively.

  • First, calculate the height of the leftmost path from the root to the bottom (this will give us the height of the tree).
  • Then, recursively check the number of nodes at each level by performing a binary search-like traversal from the root to the last level.
  • If the tree is a perfect binary tree, we can directly calculate the number of nodes as 2height - 1. Otherwise, count nodes recursively in the left and right subtrees and combine them.

Implementation

Here is the Python implementation:


class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def countNodes(self, root):
        if not root:
            return 0
        
        def treeHeight(node):
            height = 0
            while node:
                height += 1
                node = node.left
            return height
        
        def countNodesRecursive(node, height):
            if not node:
                return 0
            left_height = treeHeight(node.left)
            right_height = treeHeight(node.right)
            
            if left_height == right_height:
                return (1 << left_height) + countNodesRecursive(node.right, height - 1)
            else:
                return (1 << right_height) + countNodesRecursive(node.left, height - 1)
        
        height = treeHeight(root)
        return countNodesRecursive(root, height)
        

Here is the Java implementation:


public class Solution {
    public int countNodes(TreeNode root) {
        if (root == null) {
            return 0;
        }
        
        int height = getHeight(root);
        
        if (height == 0) {
            return 0;
        }
        
        int leftHeight = getHeight(root.left);
        int rightHeight = getHeight(root.right);
        
        if (leftHeight == rightHeight) {
            return (1 << leftHeight) + countNodes(root.right);
        } else {
            return (1 << rightHeight) + countNodes(root.left);
        }
    }
    
    private int getHeight(TreeNode node) {
        int height = 0;
        while (node != null) {
            height++;
            node = node.left;
        }
        return height;
    }
}
        

Example

Consider the following complete binary tree:

            Tree Structure:
                1
               / \
              2   3
             / \   /
            4   5 6
        

In this tree, the number of nodes is 6. The complete tree property is maintained, with all levels filled except the last one, which is as left as possible.

Another example:

            Tree Structure:
                1
               / \
              2   3
             / \
            4   5
        

In this case, the number of nodes is 5. The tree is complete, with all levels filled except the last one, which has two nodes positioned leftmost.

Complexity Analysis

Time Complexity: O(log2 n), where n is the number of nodes in the binary tree. The height of the tree is logarithmic in the number of nodes, and at each level, we perform a constant-time operation to count the nodes.

Space Complexity: O(log n), due to the recursive calls, as we are using the height of the tree as a parameter in the recursive function.

Applications

  • Helpful in determining the number of nodes in a complete binary tree where direct counting would be inefficient.
  • Efficient in solving problems related to binary heaps and trees used in priority queues.
  • Can be applied in scenarios requiring balanced binary trees for optimal search and access times.

Conclusion

The Count Complete Tree Nodes problem leverages the structure of a complete binary tree to count nodes efficiently. By using the height of the tree and performing a recursive traversal, we can calculate the number of nodes without needing to traverse every single node. This method significantly reduces the time complexity when compared to a straightforward depth-first or breadth-first search approach.

This problem is an excellent example of using tree properties to optimize operations, which is a valuable skill in algorithm design and problem-solving.

Continue Reading →