Kth Smallest Element in a BST

Difficulty: Medium

You're given the root of a binary search tree and an integer k. Find the kth smallest value stored in the tree (with k = 1 meaning the very smallest value).

Examples

Input: root = [3,1,4,null,2], k = 1
Output: 1

The values in sorted order are 1, 2, 3, 4 — the 1st smallest is 1.

Input: root = [5,3,6,2,4,null,null,1], k = 3
Output: 3

The values in sorted order are 1, 2, 3, 4, 5, 6 — the 3rd smallest is 3.

Constraints

  • The number of nodes is in the range [1, 10^4].

  • 1 <= k <= number of nodes.

Approach

The defining fact about a BST is that its in-order traversal (left, then node, then right) produces values in strictly increasing order. So the kth smallest value is simply the kth value produced by that traversal — the only question is whether you collect everything first or stop as soon as you've counted k values.

Solutions

Brute Force — Collect All Values, Then Index

Run a full in-order traversal, collecting every value into an array in sorted order. Once that's done, the answer is simply the value at index k - 1.

class TreeNode {
  constructor(val, left = null, right = null) {
    this.val = val;
    this.left = left;
    this.right = right;
  }
}

function kthSmallest(root, k) {
  const values = [];

  function inorder(node) {
    if (node === null) return;
    inorder(node.left);
    values.push(node.val);
    inorder(node.right);
  }

  inorder(root);
  return values[k - 1];
}

Time: O(n) · Space: O(n) — storing every value even when k is small

Optimal — Iterative In-Order with Early Stop

Do the same in-order traversal, but iteratively with an explicit stack, and stop the instant you've produced the kth value instead of visiting the rest of the tree. This matters a lot when k is small relative to the size of the tree.

class TreeNode {
  constructor(val, left = null, right = null) {
    this.val = val;
    this.left = left;
    this.right = right;
  }
}

function kthSmallest(root, k) {
  const stack = [];
  let node = root;

  while (node !== null || stack.length > 0) {
    while (node !== null) {
      stack.push(node);
      node = node.left;
    }

    node = stack.pop();
    k--;
    if (k === 0) return node.val;

    node = node.right;
  }

  return -1;
}

Time: O(h + k) — descends to the leftmost node, then advances k times · Space: O(h) — the explicit stack, where h is the tree's height