💡 The loop continues until the LCA is found or the tree is fully traversed.
code_explanation
Code walkthrough: Move left or right
If both p and q are less than current, move left; if both greater, move right.
💡 This step shows how the BST property guides the traversal direction.
Line:if p.val < current.val and q.val < current.val:
current = current.left
elif p.val > current.val and q.val > current.val:
current = current.right
💡 The algorithm prunes the search space by moving only in one direction.
code_explanation
Code walkthrough: Found LCA
When p and q split to different sides or match current, return current as LCA.
💡 This final step shows the stopping condition of the algorithm.
Line:else:
return current
💡 The LCA is the node where the search stops because p and q diverge.
def lowestCommonAncestor(root, p, q):
current = root # STEP 1: Initialize current to root
while current: # STEP 2: Loop while current is not None
if p.val < current.val and q.val < current.val: # STEP 3: Check if both p and q are less than current
current = current.left # STEP 3: Move left
elif p.val > current.val and q.val > current.val: # STEP 4: Check if both p and q are greater than current
current = current.right # STEP 4: Move right
else: # STEP 5: Found split point or match
return current # STEP 5: Return current as LCA
# Example usage:
# print(lowestCommonAncestor(root, p, q).val)
📊
Lowest Common Ancestor of a BST - Watch the Algorithm Execute, Step by Step
Watching each step helps you understand how the BST property guides the search efficiently without exploring unnecessary nodes.
Step 1/10
·Active fill★Answer cell
Current node: 1
628047935
Current node: 1
628047935
Current node: 1
628047935
Current node: 1
628047935
Return: 1
628047935
Return: 1
628047935
Return: 1
628047935
Return: 1
628047935
Return: 1
628047935
Return: 1
628047935
Return: 1
Key Takeaways
✓ The BST property allows the algorithm to decide direction at each node, drastically reducing search space.
This insight is hard to see from code alone because the efficiency comes from the tree structure, not just the code logic.
✓ The LCA is found at the first node where p and q values split to different subtrees or match the current node.
Understanding this split point is key to grasping why the algorithm stops early.
✓ The algorithm never needs to explore both subtrees fully, making it optimal for BSTs.
This is a concrete example of how BSTs enable efficient queries compared to general binary trees.
Practice
(1/5)
1. You need to add a new value into a binary tree such that the tree maintains the property where for every node, all values in the left subtree are smaller and all values in the right subtree are larger. Which approach guarantees this insertion is done correctly and efficiently?
easy
A. Use a breadth-first traversal to find the first empty spot and insert the new value there.
B. Perform an inorder traversal to find the correct position and then insert the new node.
C. Traverse the tree from the root, moving left or right based on comparisons, and insert the new node at the correct leaf position.
D. Use a heap insertion algorithm to maintain the tree structure.
Solution
Solution:
Step 1: Understand BST property
The tree must maintain that left children are smaller and right children are larger than the node.
Step 2: Identify insertion method
Traversing from root and choosing left or right child based on comparison ensures the new value is inserted at the correct leaf position without violating BST properties.
Final Answer:
Option C -> Option C
Quick Check:
Insertion follows BST ordering rules [OK]
Hint: BST insertion follows value comparisons down the tree [OK]
Common Mistakes:
Using BFS ignores BST ordering
Inorder traversal is for traversal, not insertion
Heap insertion is unrelated to BST
2. What is the worst-case time complexity of the optimized recursive BST node deletion algorithm that uses the in-order successor to replace a node with two children?
medium
A. O(h) where h is the height of the BST
B. O(h^2) due to recursive calls and successor search
C. O(log n) always, since BST is balanced
D. O(n) where n is the total number of nodes in the BST
Solution
Solution:
Step 1: Identify height-based operations
Deletion involves searching down the tree (O(h)) and finding the in-order successor, which is also O(h) in worst case.
Step 2: Combine operations and recursion
Successor search and recursive deletion happen along a path of length h, so total time is O(h), not O(h^2).
Final Answer:
Option A -> Option A
Quick Check:
Time proportional to tree height, not total nodes or squared height [OK]
Hint: Deletion time depends on tree height, not total nodes [OK]
Common Mistakes:
Assuming balanced BST always (log n)
Confusing recursion depth with squared complexity
Thinking successor search adds extra factor
3. Consider the following buggy code snippet for finding the kth smallest element in a BST. Which line contains the subtle bug that can cause incorrect results or runtime errors?
def kthSmallest(root: Optional[TreeNode], k: int) -> int:
stack = []
current = root
count = 0
while current or stack:
while current:
stack.append(current)
current = current.left
current = stack.pop()
count += 1
if count == k:
return current.val
current = current.right
# Bug introduced: k is used as zero-based index (count == k-1) instead of one-based
medium
A. Line with 'if count == k - 1:'
B. Line with 'count += 1'
C. Line with 'stack.append(current)'
D. Line with 'current = current.right'
Solution
Solution:
Step 1: Identify the off-by-one bug
The condition uses 'count == k - 1' which treats k as zero-based, but k is one-based in problem definition.
Step 2: Consequence of bug
This causes the function to return the (k-1)th smallest element or miss the kth element, leading to incorrect results or runtime errors if k=1.
Final Answer:
Option A -> Option A
Quick Check:
Correct condition must be 'count == k' to match one-based indexing [OK]
Hint: Check indexing base for k carefully [OK]
Common Mistakes:
Using zero-based index for k
Misplacing count increment
Returning too early
4. What is the space complexity of the optimal Morris inorder traversal approach used to recover a BST with two swapped nodes, and why might some candidates mistakenly believe it is higher?
medium
A. O(1) because Morris traversal modifies tree pointers temporarily without extra data structures
B. O(n) due to storing node values during traversal
C. O(h) where h is tree height due to recursion stack in inorder traversal
D. O(log n) because of balanced tree height and implicit stack usage
Solution
Solution:
Step 1: Understand Morris traversal space usage
Morris traversal uses threaded binary tree pointers to traverse without recursion or stack, so no extra space beyond a few pointers.
Step 2: Identify common misconception
Candidates often confuse it with recursive or stack-based inorder traversal, which uses O(h) space, or with storing values in a list, which uses O(n) space.
Final Answer:
Option A -> Option A
Quick Check:
Morris traversal achieves O(1) space by temporarily modifying tree pointers [OK]
Hint: Morris traversal uses threaded pointers, no stack needed [OK]
Common Mistakes:
Assuming recursion stack space applies
Confusing storing values with traversal space
Believing temporary pointer changes increase space
5. 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
Solution:
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.
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.
Final Answer:
Option C -> Option C
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