A general binary tree needs a full traversal to find an LCA, but a BST’s ordering lets it be found by comparing values alone: at every node, both p and q being on the same side tells you which way to go, and them straddling the current node (or one equalling it) means you have arrived.
Recursive (BST property)
Time O(h)Space O(h)If both target values are less than the current node, the LCA must be in the left subtree. If both are greater, it must be in the right subtree. Otherwise the current node is exactly where the two paths diverge (or one target is the current node) — that is the LCA.
class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right
class Solution: def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode: if p.val < root.val and q.val < root.val: return self.lowestCommonAncestor(root.left, p, q) if p.val > root.val and q.val > root.val: return self.lowestCommonAncestor(root.right, p, q) return rootComplexity: the walk follows a single downward path from root to the LCA, never branching → O(h) time, where h is the tree height (O(log n) for a balanced BST, O(n) skewed). Recursion depth matches → O(h) space.
Iterative
OptimalTime O(h)Space O(1)The recursion above is tail recursion — at each step it just moves to a child and repeats. That translates directly into a loop with no extra stack frames.
class Solution: def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode: node = root while node: if p.val < node.val and q.val < node.val: node = node.left elif p.val > node.val and q.val > node.val: node = node.right else: return nodeWatch the walk descend and prune at each step (trace data lives in this problem folder’s data.ts):
on path: 6
Decision at node 6
Start at the root, node 6. The loop holds a current node and compares p = 3 and q = 5 against its value to pick which side to descend.
Why prefer this: identical O(h) time, but no call stack is used at all → O(1) space, an improvement over the recursive version’s O(h) stack, which matters on a very deep, unbalanced BST.