The problem
You get the root of a binary search tree and an integer k (1-indexed). Return the kth smallest value in the tree.
Input: root = [5, 3, 6, 2, 4, null, null, 1], k = 3
5
/ \
3 6
/ \
2 4
/
1
Output: 3In sorted order the values are 1, 2, 3, 4, 5, 6, and the third one is 3.
How to think about it
Start with brute force. Collect every value into a list, sort it, and return values[k - 1]. That’s O(n log n) and O(n) memory. It works on any tree, which is the problem: it ignores the fact that this one is a BST.
The key insight: in-order traversal of a BST is already sorted. Visiting left subtree, then node, then right subtree yields values in increasing order. So you don’t need to sort. Walk in order and count; the kth node you visit is the answer. You can also stop the moment you reach it, without touching the rest of the tree.
Why iterative? Stopping early from deep inside a recursion is awkward (you need a counter outside and a way to unwind). With an explicit stack, “stop” is just return. The loop is the standard iterative in-order: push the whole left spine, pop one node (that’s the next smallest), then move to its right child and repeat.
Which pattern is this? Tree DFS (in-order) on a BST. The tell is “kth smallest” or “sorted order” plus “BST”. Any time a BST question mentions order, think in-order traversal.
Approach
- Start with an empty stack and
cur = root. - While
curis not empty, push it and go left. This reaches the smallest unvisited node. - Pop a node. It is the next value in sorted order, so decrease
k. - If
khits 0, return that node’s value. - Otherwise set
curto the popped node’s right child and repeat from step 2.
Solution
def kth_smallest(root, k):
st = []; cur = root
while st or cur:
while cur: st.append(cur); cur = cur.left # dive down the left spine
cur = st.pop(); k -= 1 # next value in sorted order
if k == 0: return cur.val
cur = cur.right # then its right subtree
# kth_smallest(tree[3,1,4,null,2], 1) -> 1Dry run
On the example with k = 3:
| Step | Pushed on the way left | Popped | k after |
Stack after pop |
|---|---|---|---|---|
| 1 | 5, 3, 2, 1 | 1 | 2 | [5, 3, 2] |
| 2 | nothing (1 has no right child) | 2 | 1 | [5, 3] |
| 3 | nothing (2 has no right child) | 3 | 0 | [5] |
k reaches 0 on node 3, so the answer is 3. Nodes 4, 5 and 6 are never popped.
Complexity
- Time: O(h + k). You first walk down up to h nodes to reach the minimum, then pop k nodes. In the worst case (k = n) that’s O(n).
- Space: O(h). The stack holds at most one root-to-leaf path: O(log n) balanced, O(n) skewed.
Edge cases and pitfalls
- k = 1 returns the minimum, the leftmost node.
- k = n returns the maximum; the code visits every node, which is fine.
- Off-by-one.
kis 1-indexed. Decrementing before the check (as here) is correct; checkingk == 1before decrementing also works, but don’t mix the two. - Follow-up: many queries on a changing tree. Store each node’s subtree size; then you can find the kth smallest in O(h) by comparing k with the left subtree’s size.
Related problems
- Validate Binary Search Tree (LeetCode 98): the in-order of a valid BST is strictly increasing.
- Kth Largest Element in an Array (LeetCode 215): the same “kth” question with no ordering, solved with a heap.
- Lowest Common Ancestor of a BST (LeetCode 235): another BST problem where the ordering does the work.
- 1.Maximum Depth of Binary Tree (LeetCode 104)
- 2.Same Tree (LeetCode 100)
- 3.Invert Binary Tree (LeetCode 226)
- 4.Path Sum (LeetCode 112)
- 5.Subtree of Another Tree (LeetCode 572)
- 6.Diameter of Binary Tree (LeetCode 543)
- 7.Lowest Common Ancestor of a BST (LeetCode 235)
- 8.Lowest Common Ancestor of a Binary Tree (LeetCode 236)
- 9.Validate Binary Search Tree (LeetCode 98)
- 10.Kth Smallest Element in a BST (LeetCode 230)
- 11.Construct Binary Tree from Preorder and Inorder (LeetCode 105)
- 12.Serialize and Deserialize Binary Tree (LeetCode 297)
- 13.Binary Tree Maximum Path Sum (LeetCode 124)