Loading problems...
TL;DR: Perform a recursive inorder traversal to visit nodes in strictly ascending order, decrementing a counter k until it reaches zero to identify the target value.
The LeetCode 230 problem, "Kth Smallest Element in a BST," asks us to find the -th smallest value within a Binary Search Tree (BST). Given the root of the tree and an integer , we must return the value of the node that would appear at the -th position (1-indexed) if all nodes were sorted by value.
This is a fundamental interview question that tests your understanding of BST properties and tree traversal algorithms.
A naive approach to solving the Kth Smallest Element in a BST involves ignoring the specific structural properties of the BST and treating it as a generic binary tree.
k-1.Pseudo-code:
textfunction bruteForce(root, k): list = [] traverse(root, list) // adds all nodes to list sort(list) return list[k-1]
Complexity Analysis:
Why it fails: While this approach produces the correct answer, it is computationally inefficient. It fails to utilize the inherent sorted property of the Binary Search Tree. Furthermore, storing all elements is unnecessary when we only need the -th element, leading to suboptimal space usage.
The key intuition for the optimal solution lies in the relationship between the BST property and Inorder Traversal.
In a BST:
When we execute a recursive inorder traversal, the algorithm prioritizes the left child. It dives as deep as possible into the left subtree before processing a node. This means the very first node "processed" (or visited) by the inorder logic is the minimum element in the tree. The second node processed is the second smallest, and so on.
Instead of storing values, we can maintain a counter. As the recursion unwinds from the left, we increment our count of visited nodes. When the count equals , the current node is our answer.
Visual Description:
Visualize the recursion stack growing as the algorithm traverses down to the leftmost leaf. At this point, the stack depth is equal to the height of the tree. The algorithm hits a null left child and returns to the leaf node. This leaf is the "1st smallest." The algorithm then attempts to go right. If no right child exists, it pops the stack to the parent, which becomes the "2nd smallest." This sequence strictly follows the numerical order of the values.

To implement this efficiently, we use a Depth-First Search (DFS) strategy specifically following the Inorder scheme.
left child. This ensures we process smaller numbers first.right child.This approach ensures we only visit the necessary nodes. Once the -th element is found, the remaining traversal is skipped (or effectively ignored).
Let's trace the execution for root = [5,3,6,2,4], k = 3.
DFS(5.left) DFS(3).DFS(3.left) DFS(2).DFS(2.left) DFS(null). Returns.DFS(2.right) DFS(null). Returns. Node 2 function completes.DFS(3.right) DFS(4).DFS(4.left) DFS(null). Returns.The correctness relies on the fundamental theorem of Binary Search Trees: an inorder traversal of a BST yields the keys in monotonically increasing order.
cpp/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} * }; */ class Solution { public: int kthSmallest(TreeNode* root, int k) { int result = -1; inorder(root, k, result); return result; } private: // Standard Inorder Traversal: Left -> Root -> Right void inorder(TreeNode* node, int& k, int& result) { if (!node) return; // Traverse left subtree inorder(node->left, k, result); // Process current node k--; if (k == 0) { result = node->val; return; } // Optimization: stop if result is already found if (result != -1) return; // Traverse right subtree inorder(node->right, k, result); } };
java/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode() {} * TreeNode(int val) { this.val = val; } * TreeNode(int val, TreeNode left, TreeNode right) { * this.val = val; * this.left = left; * this.right = right; * } * } */ class Solution { private int count; private int result; public int kthSmallest(TreeNode root, int k) { count = k; result = -1; inorder(root); return result; } private void inorder(TreeNode node) { if (node == null) return; // Traverse left inorder(node.left); // Process current node count--; if (count == 0) { result = node.val; return; // Found the kth element } // Early exit optimization if (result != -1) return; // Traverse right inorder(node.right); } }
python# Definition for a binary tree node. # class TreeNode: # def __init__(self, val=0, left=None, right=None): # self.val = val # self.left = left # self.right = right class Solution: def kthSmallest(self, root: Optional[TreeNode], k: int) -> int: self.k = k self.result = None def inorder(node): if not node or self.result is not None: return # Traverse Left inorder(node.left) # Process Node self.k -= 1 if self.k == 0: self.result = node.val return # Traverse Right inorder(node.right) inorder(root) return self.result
Time Complexity:
Space Complexity:
The Tree DFS - Recursive Inorder Traversal pattern is versatile and appears in several other popular interview questions:
Mastering this pattern allows you to solve almost any BST problem that involves order or sorting.
Why does my solution return the wrong number?
Why is my solution running out of memory?
Why does the recursion not stop after finding the answer?
if result != -1 return) after the recursive calls.