Approach Summary
In-order traversal of BST visits nodes in ascending order. Count k nodes; return on the kth.
Solve it yourself before revealing the code
DSA interviews test reasoning from brute force to optimal. Think through the constraints first.
Solution Progression (Brute Force → Most Optimized)
Understand the architectural evolution from naive baseline to optimal complexity.
| Approach | Time | Space | Core Strategy / Trade-off |
|---|---|---|---|
| 1 Approach 1: In-Order Traversal with Early Exit (Optimal) | O(H + k) | O(H) | Traverse left-root-right, stopping traversal as soon as the kth visited element is reached. |
| 2 Approach 2: Recursive In-Order Traversal to List (Baseline) | O(n) | O(n) | Collects all node values in ascending order via full in-order traversal, returning list[k - 1]. |
Approach 1: In-Order Traversal with Early Exit (Optimal)
In-order traversal of a BST enumerates elements in ascending order. Increment counter upon visiting each node; as soon as counter == k, record answer and terminate.
Approach 1: In-Order Traversal with Early Exit (Optimal) Implementation
Approach 1: In-Order Traversal with Early Exit (Optimal)
class Solution {
public int kthSmallest(TreeNode root, int k) {
Stack<TreeNode> stack = new Stack<>();
TreeNode curr = root;
while (curr != null || !stack.isEmpty()) {
while (curr != null) {
stack.push(curr);
curr = curr.left;
}
curr = stack.pop();
if (--k == 0) return curr.val;
curr = curr.right;
}
return -1;
}
}class Solution {
public:
int kthSmallest(TreeNode* root, int k) {
stack<TreeNode*> s;
TreeNode* curr = root;
while (curr != NULL || !s.empty()) {
while (curr != NULL) {
s.push(curr);
curr = curr->left;
}
curr = s.top(); s.pop();
if (--k == 0) return curr->val;
curr = curr->right;
}
return -1;
}
};class Solution:
def kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
stack = []
curr = root
while curr or stack:
while curr:
stack.append(curr)
curr = curr.left
curr = stack.pop()
k -= 1
if k == 0:
return curr.val
curr = curr.rightfunction kthSmallest(root, k) {
const stack = [];
let curr = root;
while (curr || stack.length) {
while (curr) {
stack.push(curr);
curr = curr.left;
}
curr = stack.pop();
k--;
if (k === 0) return curr.val;
curr = curr.right;
}
} Approach 2: Recursive In-Order Traversal to List (Baseline)
Performs complete in-order traversal (left, root, right) of the BST and appends every element to a list. Because BST in-order is sorted, returns the (k-1)-th index.
Approach 2: Recursive In-Order Traversal to List (Baseline) Implementation
Approach 2: Recursive In-Order Traversal to List (Baseline)
class Solution {
private List<Integer> vals = new ArrayList<>();
private void inorder(TreeNode node) {
if (node == null) return;
inorder(node.left);
vals.add(node.val);
inorder(node.right);
}
public int kthSmallest(TreeNode root, int k) {
inorder(root);
return vals.get(k - 1);
}
}class Solution {
vector<int> vals;
void inorder(TreeNode* node) {
if (!node) return;
inorder(node->left);
vals.push_back(node->val);
inorder(node->right);
}
public:
int kthSmallest(TreeNode* root, int k) {
inorder(root);
return vals[k - 1];
}
};class Solution:
def kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
vals = []
def inorder(node):
if not node: return
inorder(node.left)
vals.append(node.val)
inorder(node.right)
inorder(root)
return vals[k - 1]function kthSmallest(root, k) {
const vals = [];
function inorder(node) {
if (!node) return;
inorder(node.left);
vals.push(node.val);
inorder(node.right);
}
inorder(root);
return vals[k - 1];
} Edge Cases to Watch
- k = 1 (smallest element; leftmost node in tree)
- k equals total number of nodes (largest element; rightmost node)
- Left-skewed tree
Master the Trees / DFS Pattern
Study the core invariant, step-by-step decision framework, and common interview traps for the Trees / DFS pattern.
How to Recognize This Pattern
- "kth element in BST"
- In-order traversal of BST = sorted ascending
Complexity Analysis
Time Complexity
O(H + k)
Space Complexity
O(H)