Problem
Given a binary search tree and a target integer, find the node whose value equals the target and return the entire subtree rooted at that node. If no such node exists, return null. The critical detail is that you return the subtree โ the node and everything below it โ not just the integer value.
[4,2,7,1,3]
- Input: root = [4, 2, 7, 1, 3], val = 2
- Output: [2, 1, 3]
- Explanation: Node 2 is found; its subtree (including children 1 and 3) is returned.
Searching for a missing value like val = 5 returns null because 5 does not appear anywhere in the tree.
Intuition
A BST is organized so that every node's left subtree contains only smaller values and its right subtree contains only larger values. At every node you face a binary decision: if the target is smaller, the answer can only live to the left; if larger, only to the right. You follow this single-direction chain until you either find the target or fall off the tree.
Approach 1 โ Recursive
At each node, compare the target to the current value and recurse into the one subtree that could possibly contain it. The base cases handle both a successful match and exhausting the tree.
- If the current node is null, the target is not in the tree โ return null.
- If the current node's value equals
val, return the current node (this is the subtree root). - If
valis less than the current value, recurse into the left child. - Otherwise, recurse into the right child.
1def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
2 # Null means not found; matching value means return this subtree
3 if not root or root.val == val:
4 return root
5 if val < root.val:
6 return self.searchBST(root.left, val)
7 return self.searchBST(root.right, val)Time: O(h) where h is the tree height โ O(log n) for a balanced BST, O(n) for a fully skewed one.
Space: O(h) โ each recursive call adds a frame to the call stack.
Approach 2 โ Iterative
Replace the recursion with a while loop, walking one pointer down the tree. This eliminates call-stack overhead without changing the traversal logic.
- Initialize a
currentpointer to the root. - While
currentis not null:- If
current.valequalsval, returncurrent. - If
valis less thancurrent.val, movecurrentto its left child. - Otherwise, move
currentto its right child.
- If
- The loop exits only when
currentis null โ the target was not found; return null.
1def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
2 current = root
3 while current:
4 if current.val == val:
5 return current
6 # BST property narrows the search to exactly one subtree each step
7 current = current.left if val < current.val else current.right
8 return NoneTime: O(h) โ identical traversal path to the recursive approach.
Space: O(1) โ only a single pointer walks the tree; no call stack grows.
Complexity Summary
| Approach | Time | Space | When to use |
|---|---|---|---|
| Recursive | O(h) | O(h) | When tree height is bounded and concise recursive code is preferred |
| Iterative | O(h) | O(1) | When the tree may be heavily skewed and call-stack depth is a concern |
Common Mistakes
- Returning the integer value instead of the node โ the problem asks for the subtree rooted at the matching node, not just
root.val; returning the number passes simple tests but breaks any caller that needs to traverse the subtree. - Searching both subtrees instead of one โ ignoring the BST property and recursing into both children degrades the search from O(h) to O(n); the whole point of a BST is that the comparison eliminates one entire half.
- Swapping left and right โ going right when
val < root.valis a direction inversion; a reliable mnemonic is "smaller means left" since BST order mirrors sorted-array order: smaller indices are to the left. - Mutating the
rootparameter in the iterative version โ writingroot = root.leftinstead ofcurrent = root.leftoverwrites the function's local reference to the tree root, which can silently corrupt the traversal if the compiler optimizes the parameter or if the variable is reused. - Omitting the null return after the iterative loop โ in Python the function implicitly returns
None, which happens to be correct, but in Java or C++ the missing return is a compile error; always make the null case explicit.
Related Problems
Kth Smallest Element in a BSTโ exploits BST inorder ordering to locate the kth value without visiting the whole treeLowest Common Ancestor of a Binary Search Treeโ uses the same left/right comparison logic to navigate toward two target nodes simultaneouslyDelete Node in a BSTโ first locates the target using this exact search, then restructures the subtree to maintain BST validityConvert Sorted Array to Binary Search Treeโ constructs the BST whose structure makes this search pattern possible