↓Skip to main content
  1. LeetCode/

LeetCode 222: Count Complete Tree Nodes

·2 mins· ·
LeetCode Medium Binary-Search Bit-Manipulation Tree Binary-Tree
Wei Yi Chung
Author
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
Table of Contents

Meta Data
#

Difficulty: medium First Attempt: 2022-11-18

  • Submissions: Runtime Error → Accepted ×3 → Restrictions Failed → Accepted

Approach
#

For a complete tree, compare the leftmost depths of the left and right subtrees (Tree):

  • Equal: the left subtree is perfect with 2^h - 1 nodes; add the root and recurse on the right.
  • Right shallower: the right subtree is perfect (one level shorter); recurse on the left.

Each level recurses on one side and each height costs O(log n), so O(log² n) in total.

My Attempts
#

In 2022 the first version had an undefined variable, and then a plain node-counting traversal (O(n)) passed. Rewriting it in 2026, I compared the leftmost and rightmost heights: equal means the whole tree is perfect and uses the formula, otherwise recurse on both sides, also O(log² n). The version here compares the two subtrees’ leftmost depths and recurses on only one side per level.

Solution
#

class Solution:
    def countNodes(self, root: Optional[TreeNode]) -> int:
        def depth(node):
            d = 0
            while node:
                d, node = d + 1, node.left
            return d
        if not root:
            return 0
        l, r = depth(root.left), depth(root.right)
        if l == r:                                   # 左子樹是滿的
            return (1 << l) + self.countNodes(root.right)
        return (1 << r) + self.countNodes(root.left)    # 右子樹是滿的

Complexity
#

Time O(log² n), space O(log n).

Mistakes to Avoid
#

  • 1 << h already includes the root: 2^h - 1 subtree nodes plus 1.

Interview Explanation
#

In a complete tree one subtree is always perfect. I compare the leftmost depths, count the perfect side by formula, and recurse on the other. One side per level, so O(log² n).

Related

LeetCode 113: Path Sum II
·2 mins
LeetCode Medium Backtracking Tree Depth-First-Search Binary-Tree
LeetCode 113 note: backtrack with the current path and store a copy at a leaf whose total matches; values can be negative, so no early pruning
LeetCode 129: Sum Root to Leaf Numbers
·1 min
LeetCode Medium Tree Depth-First-Search Binary-Tree
LeetCode 129 note: on the way down multiply the current number by 10 and add the node’s value, adding it to the total at a leaf
LeetCode 236: Lowest Common Ancestor of a Binary Tree
·2 mins
LeetCode Medium Tree Depth-First-Search Binary-Tree Binary-Lifting
LeetCode 236 note: recursion returns whichever of p or q a subtree contains; finding something on both sides means they split here, so this node is the LCA
LeetCode 337: House Robber III
·2 mins
LeetCode Medium Dynamic-Programming Tree Depth-First-Search Binary-Tree
LeetCode 337 note: tree DP where each node returns the best (rob it, skip it) pair; not robbing alternate levels
LeetCode 102: Binary Tree Level Order Traversal
·1 min
LeetCode Medium Tree Breadth-First-Search Binary-Tree
LeetCode 102 note: BFS one whole level at a time, building the next level from the current one; an empty tree returns an empty list
LeetCode 1448: Count Good Nodes in Binary Tree
·1 min
LeetCode Medium Tree Depth-First-Search Breadth-First-Search Binary-Tree
LeetCode 1448 note: pass the path maximum down during DFS; a node is good when its value is at least that maximum