Bird
Raised Fist0
Interview Prepbinary-search-treeseasyAmazonGoogleFacebook

Convert Sorted Array to Height-Balanced BST

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 and start recursion

Initialize index to 0 and start helper recursion with full array range (0 to 4).

💡 Index tracks nodes created; starting with full range means building entire tree.
Line:self.index = 0 return self.helper(nums, 0, len(nums) - 1)
💡 The entire array is considered initially to build the root and subtrees.
📊
Convert Sorted Array to Height-Balanced BST - Watch the Algorithm Execute, Step by Step
Watching each recursive call and node creation helps you understand how the algorithm balances the tree by choosing midpoints and how recursion unwinds to assemble the final BST.
Step 1/20
·Active fillAnswer cell
DFS Stack
null (entered)left=0 right=4 mid=null
DFS Stack
null (entered)left=0 right=4 mid=2
DFS Stack
null (entered)left=0 right=1 mid=nullnull (entered)left=0 right=4 mid=2
DFS Stack
null (entered)left=0 right=1 mid=0null (entered)left=0 right=4 mid=2
DFS Stack
null (entered)left=0 right=-1 mid=nullnull (entered)left=0 right=1 mid=0null (entered)left=0 right=4 mid=2
Current node: 1
-10
DFS Stack
1 (left_done)left=0 right=1 mid=0null (entered)left=0 right=4 mid=2
-10
DFS Stack
null (entered)left=1 right=1 mid=null1 (left_done)left=0 right=1 mid=0null (entered)left=0 right=4 mid=2
-10
DFS Stack
null (entered)left=1 right=1 mid=11 (left_done)left=0 right=1 mid=0null (entered)left=0 right=4 mid=2
-10
DFS Stack
null (entered)left=1 right=0 mid=nullnull (entered)left=1 right=1 mid=11 (left_done)left=0 right=1 mid=0null (entered)left=0 right=4 mid=2
Current node: 2
-10-3
DFS Stack
1 (right_done)left=0 right=1 mid=0null (entered)left=0 right=4 mid=2
Current node: 3
-10-3
DFS Stack
null (left_done)left=0 right=4 mid=2
Return: 1
Current node: 3
-10-30
DFS Stack
3 (left_done)left=0 right=4 mid=2
-10-30
DFS Stack
null (entered)left=3 right=4 mid=null3 (left_done)left=0 right=4 mid=2
-10-30
DFS Stack
null (entered)left=3 right=4 mid=33 (left_done)left=0 right=4 mid=2
-10-30
DFS Stack
null (entered)left=3 right=2 mid=nullnull (entered)left=3 right=4 mid=33 (left_done)left=0 right=4 mid=2
Current node: 4
-10-305
DFS Stack
4 (left_done)left=3 right=4 mid=33 (left_done)left=0 right=4 mid=2
-10-305
DFS Stack
null (entered)left=4 right=4 mid=null4 (left_done)left=3 right=4 mid=33 (left_done)left=0 right=4 mid=2
-10-305
DFS Stack
null (entered)left=4 right=4 mid=44 (left_done)left=3 right=4 mid=33 (left_done)left=0 right=4 mid=2
-10-305
DFS Stack
null (entered)left=4 right=3 mid=nullnull (entered)left=4 right=4 mid=44 (left_done)left=3 right=4 mid=33 (left_done)left=0 right=4 mid=2
Current node: 3
-10-3059
Return: 3

Key Takeaways

Choosing the middle element as root at each recursive step ensures the BST is height-balanced.

This insight is hard to see from code alone but clear when watching the recursive splits and node creations.

The recursion builds left subtree first, then root, then right subtree, which is crucial for correct BST construction.

Understanding the order of recursion helps grasp how the tree nodes are linked properly.

Base cases where left > right stop recursion and return None, marking leaf nodes' children.

Visualizing base cases clarifies when recursion ends and how leaf nodes are formed.

Practice

(1/5)
1. You are given a binary search tree and two nodes within it. You need to find the node that is the deepest ancestor common to both nodes, leveraging the BST property to optimize the search. Which approach guarantees the most efficient solution?
easy
A. Perform two separate DFS traversals to find paths from root to each node, then compare paths to find the last common node.
B. Apply dynamic programming to store ancestors of each node and then find the lowest common ancestor by comparing stored data.
C. Iteratively traverse the BST from the root, moving left or right depending on the values of the two nodes relative to the current node, stopping when the current node splits the paths to the two nodes.
D. Use a greedy approach that always moves towards the node with the smaller value until both nodes are found.

Solution

  1. Step 1: Understand BST property usage

    In a BST, left subtree nodes are smaller and right subtree nodes are larger than the current node. This allows pruning the search space efficiently.
  2. Step 2: Identify optimal traversal

    Starting from root, if both target nodes are smaller, go left; if both are larger, go right; else current node is the split point and thus the LCA.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Iterative BST traversal uses O(h) time and O(1) space [OK]
Hint: Use BST property to prune search paths [OK]
Common Mistakes:
  • Using path comparison wastes time and space
  • Greedy approach ignores split point logic
  • Dynamic programming is unnecessary overhead
2. What is the time complexity of the iterative inorder traversal approach to find the kth smallest element in a BST, where H is the height of the tree and k is the input parameter?
medium
A. O(H + k), where H is the height of the tree and k is the kth element to find
B. O(k), since only k nodes are visited
C. O(k log n), assuming balanced BST
D. O(n), where n is the total number of nodes in the BST

Solution

  1. Step 1: Analyze traversal steps

    The algorithm traverses down to the leftmost node (cost O(H)) and then visits k nodes in inorder sequence.
  2. Step 2: Combine costs

    Total time is O(H) to reach leftmost node plus O(k) to visit k nodes, so O(H + k).
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Traversal cost depends on height plus k nodes visited [OK]
Hint: Traversal cost includes height plus k nodes visited [OK]
Common Mistakes:
  • Assuming O(n) always
  • Ignoring height cost
  • Assuming only k nodes visited without stack overhead
3. What is the worst-case time complexity of the optimal iterative BST search algorithm when searching for a value in a BST with n nodes and height h?
medium
A. O(log n) always because BSTs are balanced.
B. O(n) because you might have to visit every node in the tree.
C. O(h) because the search path follows the height of the tree.
D. O(1) because the search uses direct indexing.

Solution

  1. Step 1: Understand BST height and search path

    The search path length is at most the height h of the BST, as each step moves down one level.
  2. Step 2: Analyze worst-case time complexity

    In worst case (unbalanced tree), h can be up to n, but complexity is expressed as O(h), not O(n) directly.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Search complexity depends on tree height, not total nodes necessarily [OK]
Hint: Time depends on tree height, not total nodes always [OK]
Common Mistakes:
  • Assuming O(log n) always, ignoring unbalanced trees
4. The following code attempts to find if there exist two distinct nodes in a BST whose values sum to k. Identify the line containing the subtle bug that can cause incorrect results.
medium
A. Line 6: dfs(node.left)
B. Line 4: if k - node.val in seen:
C. Line 7: seen.add(node.val)
D. Line 8: dfs(node.right)

Solution

  1. Step 1: Understand DFS and set usage

    The code checks if complement exists in seen before adding current node's value.
  2. Step 2: Identify bug in order of operations

    Checking complement before adding current node's value misses pairs where both nodes are the same, or misses valid pairs if current node's value is needed for complement checks in children.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Complement check must happen after adding current node's value to seen [OK]
Hint: Add current node to set before checking complements [OK]
Common Mistakes:
  • Checking complement before adding current node's value
  • Not handling None nodes properly
  • Returning False too early
5. Suppose you want to modify the BST insertion algorithm to allow inserting duplicate values by always inserting duplicates into the left subtree. Which of the following changes to the iterative insertion code below correctly implements this behavior without breaking the BST property?
def insertIntoBST(root, val):
    if root is None:
        return TreeNode(val)
    curr = root
    while curr:
        parent = curr
        if val < curr.val:
            if curr.left is None:
                curr.left = TreeNode(val)
                return root
            curr = curr.left
        else:
            if curr.right is None:
                curr.right = TreeNode(val)
                return root
            curr = curr.right
    return root
hard
A. Change the condition to if val <= curr.val: and insert duplicates to the left subtree.
B. Change the condition to if val < curr.val: and insert duplicates to the right subtree.
C. Always insert duplicates as new root nodes to maintain BST property.
D. Disallow duplicates by returning the original tree without insertion.

Solution

  1. Step 1: Understand duplicate insertion rule

    Duplicates must go to the left subtree, so values equal to current node should be treated as less or equal.
  2. Step 2: Modify comparison operator

    Changing condition to val <= curr.val ensures duplicates follow left subtree insertion path, preserving BST property.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Duplicates inserted left by using <= comparison [OK]
Hint: Use <= to direct duplicates left, preserving BST order [OK]
Common Mistakes:
  • Inserting duplicates right breaks problem requirement
  • Inserting duplicates as new roots breaks BST
  • Ignoring duplicates causes infinite recursion