Bird
Raised Fist0
Interview Preptree-dfseasyAmazonGoogle

Count Complete Tree Nodes

Choose your preparation mode4 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Steps
setup

Initialize root and start height computation

Start computing the height of the tree by initializing height counter and setting current node to root.

💡 Computing height by going down left children helps determine the number of levels in the tree.
Line:h = 0 while root: h += 1 root = root.left
💡 Height is the number of levels, which guides the binary search range for last level nodes.
📊
Count Complete Tree Nodes - Watch the Algorithm Execute, Step by Step
Watching each step reveals how the algorithm efficiently counts nodes without traversing every node, using tree properties and binary search.
Step 1/13
·Active fillAnswer cell
Current node: 1
123456
Current node: 1
123456
123456
123456
Current node: 2
123456
Return: true
123456
123456
Current node: 3
123456
Return: true
123456
123456
Current node: 3
123456
Return: false
123456
123456
Return: 6

Key Takeaways

The algorithm efficiently counts nodes by leveraging the complete tree's height and binary search on the last level.

This insight is hard to see from code alone because it avoids naive traversal and uses tree properties cleverly.

Binary search narrows down the last level nodes by checking existence through bitwise traversal.

Visualizing the traversal path for each index clarifies how the algorithm decides left or right moves.

The final count combines nodes above the last level and the count of existing nodes found on the last level.

Understanding this sum is key to grasping why the algorithm returns the correct total node count.

Practice

(1/5)
1. Consider the following code snippet implementing the optimal DFS approach for the Path Sum problem. Given the tree below and targetSum = 22, what is the return value of the function call hasPathSum(root, 22)? Tree structure: - root = TreeNode(5) - root.left = TreeNode(4) - root.right = TreeNode(8) - root.left.left = TreeNode(11) - root.left.left.left = TreeNode(7) - root.left.left.right = TreeNode(2) - root.right.left = TreeNode(13) - root.right.right = TreeNode(4) - root.right.right.right = TreeNode(1)
def hasPathSum(root: Optional[TreeNode], targetSum: int) -> bool:
    def dfs(node, curr_sum):
        if not node:
            return False
        curr_sum += node.val
        if not node.left and not node.right:
            return curr_sum == targetSum
        return dfs(node.left, curr_sum) or dfs(node.right, curr_sum)
    return dfs(root, 0)
easy
A. True
B. False
C. Raises an exception due to null pointer
D. Returns True only if the root value equals targetSum

Solution

  1. Step 1: Trace the path sums

    Check root-to-leaf paths: - 5↔4↔11↔7 = 27 - 5↔4↔11↔2 = 22 (matches targetSum) - 5↔8↔13 = 26 - 5↔8↔4↔1 = 18 Since one path sums to 22, the function returns True.
  2. Step 2: Confirm code logic

    The DFS returns True as soon as it finds the matching path sum at a leaf node.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Path 5↔4↔11↔2 sums to 22, so return True [OK]
Hint: Check all root-to-leaf paths, not just partial sums [OK]
Common Mistakes:
  • Stopping at non-leaf nodes
  • Ignoring leaf node condition
2. What is the time complexity of the brute force approach that separately computes height for each node to check if a binary tree is balanced?
medium
A. O(n^2)
B. O(n)
C. O(n log n)
D. O(n h) where h is tree height

Solution

  1. Step 1: Analyze height computation calls

    Height is computed recursively for each node, and each height call traverses subtree nodes.
  2. Step 2: Calculate total calls

    For n nodes, height is called at each node, and each call can take O(n) in worst case, leading to O(n^2) total time.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Repeated height calls cause quadratic time [OK]
Hint: Repeated height calls cause O(n²) time [OK]
Common Mistakes:
  • Assuming height calls are O(1) leading to O(n) time
  • Confusing height with depth or tree height h
  • Thinking O(n log n) due to balanced tree assumption
3. Consider this buggy iterative postorder traversal code:
def postorderTraversal(root):
    result = []
    stack = []
    last_visited = None
    current = root
    while current or stack:
        while current:
            stack.append(current)
            current = current.left
        peek_node = stack[-1]
        if peek_node.right and last_visited == peek_node.right:
            current = peek_node.right
        else:
            result.append(peek_node.val)
            last_visited = stack.pop()
    return result
What is the bug in this code?
medium
A. The inner while loop should traverse right children instead of left
B. The condition should check if last_visited != peek_node.right, not == peek_node.right
C. The last_visited variable is never updated
D. The result list is appended before traversing the left subtree

Solution

  1. Step 1: Examine condition for traversing right subtree

    Correct logic requires moving to right child if it exists and was not visited yet, so condition must be last_visited != peek_node.right.
  2. Step 2: Identify effect of wrong condition

    Using last_visited == peek_node.right causes skipping right subtree traversal or infinite loops.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Fixing condition restores correct postorder traversal [OK]
Hint: Check last_visited != right child to avoid revisiting [OK]
Common Mistakes:
  • Using == instead of !=
  • Not updating last_visited
  • Appending too early
4. Suppose you want to perform inorder traversal on a binary tree where nodes can have parent pointers but no left or right child pointers. Which approach correctly produces the inorder sequence without recursion or extra stack?
hard
A. Use Morris traversal by creating threads on parent pointers instead of child pointers.
B. Use breadth-first search since parent pointers allow level order traversal.
C. Use recursive traversal ignoring parent pointers, which will fail due to missing child links.
D. Use iterative traversal with a pointer to the current node and track previously visited node to decide traversal direction.

Solution

  1. Step 1: Understand traversal constraints

    Without left/right child pointers, Morris traversal is not applicable since it relies on child links.
  2. Step 2: Use parent pointers to simulate traversal

    By tracking current and previously visited nodes, we can move up or down the tree to simulate inorder traversal iteratively.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Tracking previous node enables correct traversal without extra space [OK]
Hint: Parent pointers + prev node tracking enable traversal [OK]
Common Mistakes:
  • Trying to create threads on parent pointers
  • Using recursion without child pointers
  • Confusing BFS with inorder traversal
5. Suppose the binary tree nodes can have duplicate values, and you are given preorder and inorder traversals with duplicates. Which modification to the standard iterative approach is necessary to correctly reconstruct the tree?
hard
A. Use a hash map from value to a list of all indices in inorder, and track which index to use next during construction.
B. Ignore duplicates and build the tree as usual, since preorder and inorder uniquely identify the tree.
C. Sort the preorder array to remove duplicates before building the tree.
D. Use a brute force approach with array slicing to handle duplicates correctly.

Solution

  1. Step 1: Understand the problem with duplicates

    Duplicates cause ambiguity in mapping values to inorder indices, breaking the unique root index lookup.
  2. Step 2: Modify data structure

    Store all indices of each value in a list, and track which occurrence to use next to maintain correct subtree boundaries.
  3. Step 3: Avoid naive approaches

    Ignoring duplicates or sorting breaks traversal properties; brute force is inefficient and unnecessary with proper tracking.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    Tracking multiple indices per value resolves duplicate ambiguity [OK]
Hint: Track all inorder indices per value to handle duplicates [OK]
Common Mistakes:
  • Assuming unique values always
  • Sorting preorder breaks tree structure
  • Using brute force causes inefficiency