ProgramGuru

Find the kth Smallest Element in a Binary Search Tree

Problem and examples

Given the root of a Binary Search Tree (BST) and an integer k, return the kth smallest value among all the nodes in the BST. The BST property ensures that the left subtree contains only nodes with values less than the root, and the right subtree only nodes with values greater than the root.

You can assume that 1 ≤ k ≤ N, where N is the number of nodes in the tree.

Input Tree k Output Description
[5, 3, 7, 2, 4, 6, 8] 3 4 In-order traversal gives [2, 3, 4, 5, 6, 7, 8], so 3rd smallest is 4
[10, 5, 15, 3, 7, null, 18] 4 10 In-order: [3, 5, 7, 10, 15, 18]; 4th element is 10
[20, 8, 22, 4, 12, null, null, null, null, 10, 14] 5 14 In-order: [4, 8, 10, 12, 14, 20, 22]; 5th element is 14
[3, 1, 4, null, 2] 1 1 In-order: [1, 2, 3, 4]; 1st element is 1
[2, 1, 3] 2 2 In-order: [1, 2, 3]; 2nd element is 2
[1] 1 1 Single node is the only (and thus 1st) element in-order

Explore Find the kth Smallest Element in a BST

Load an example or enter your own input. Use the player controls to follow each change.

Understanding the Problem

We are given a Binary Search Tree (BST), and we are asked to find the kth smallest element in it. A Binary Search Tree has the special property that for any given node, all elements in its left subtree are smaller, and all elements in its right subtree are larger.

This means that if we perform an in-order traversal of the BST (visit left → root → right), we will visit the nodes in ascending order. By keeping count as we traverse, we can return the kth node visited, which will be the kth smallest element.

Step-by-Step Solution with Example

step 1: Choose a sample BST and the value of k

Let’s take the following BST:


        5
       /       3   7
     /        2   4   8

Suppose k = 3. We want to find the 3rd smallest element.

step 2: Perform in-order traversal (left → root → right)

During in-order traversal, we visit nodes in this order:

2 → 3 → 4 → 5 → 7 → 8

We count as we go. The 3rd element visited is 4.

step 3: Implement in-order traversal with a counter

As we recursively traverse, we pass a counter to track how many nodes we have visited. Once the counter equals k, we stop and return that node’s value.

step 4: Handle base cases

If the current node is null or we’ve already found the result, we simply return. This prevents unnecessary traversal once our answer is found.

step 5: Return the result

Once we reach the kth node, we store the value and return it. This value is our answer.

Edge Cases

Empty Tree

If the tree is null, there is no kth smallest element to find. In this case, we should return None or raise an error depending on requirements.

k is larger than total number of nodes

For example, if the tree has 4 nodes and k = 6, we cannot find the 6th smallest. We should check this condition and return an appropriate message or exception.

k is 1 or equal to total nodes

When k = 1, we are looking for the smallest element — the leftmost node. When k equals total number of nodes, we are looking for the largest — the rightmost node. The algorithm still works but make sure traversal reaches these nodes correctly.

Finally

This problem is a classic example of leveraging the properties of BSTs. Using in-order traversal is both natural and efficient for this task. For beginners, it's important to understand how traversal order affects the result. Always consider special scenarios like empty trees or out-of-bound values of k to build a robust solution.

With this approach, you're not just solving the problem — you're developing a strong grasp of tree traversal techniques.

  1. Given a binary search tree (BST) and an integer k.
  2. Perform an in-order traversal of the BST, which visits nodes in ascending order.
  3. Keep a counter to track the number of nodes visited.
  4. When the counter equals k, record the current node's value as the kth smallest element.
  5. Return the recorded value as the result.

Implementation and efficiency

C implementation

#include <stdio.h>
#include <stdlib.h>

typedef struct TreeNode {
    int val;
    struct TreeNode *left, *right;
} TreeNode;

TreeNode* createNode(int val) {
    TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));
    node->val = val;
    node->left = node->right = NULL;
    return node;
}

void inorder(TreeNode* root, int k, int* count, int* result) {
    if (!root) return;
    inorder(root->left, k, count, result);
    (*count)++;
    if (*count == k) {
        *result = root->val;
        return;
    }
    inorder(root->right, k, count, result);
}

int kthSmallest(TreeNode* root, int k) {
    int count = 0, result = -1;
    inorder(root, k, &count, &result);
    return result;
}

int main() {
    TreeNode* root = createNode(3);
    root->left = createNode(1);
    root->right = createNode(4);
    root->left->right = createNode(2);
    printf("%d\n", kthSmallest(root, 1));
    return 0;
}

C++ implementation

#include <iostream>
using namespace std;

struct TreeNode {
    int val;
    TreeNode *left, *right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

class Solution {
    int count = 0;
    int result = -1;
public:
    int kthSmallest(TreeNode* root, int k) {
        inorder(root, k);
        return result;
    }
    void inorder(TreeNode* node, int k) {
        if (!node) return;
        inorder(node->left, k);
        count++;
        if (count == k) {
            result = node->val;
            return;
        }
        inorder(node->right, k);
    }
};

int main() {
    TreeNode* root = new TreeNode(3);
    root->left = new TreeNode(1);
    root->right = new TreeNode(4);
    root->left->right = new TreeNode(2);
    Solution sol;
    cout << sol.kthSmallest(root, 1) << endl;
    return 0;
}

Python implementation

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, k):
        self.count = 0
        self.result = None

        def inorder(node):
            if not node or self.result is not None:
                return
            inorder(node.left)
            self.count += 1
            if self.count == k:
                self.result = node.val
                return
            inorder(node.right)

        inorder(root)
        return self.result

# Example
if __name__ == '__main__':
    root = TreeNode(3, TreeNode(1, None, TreeNode(2)), TreeNode(4))
    sol = Solution()
    print(sol.kthSmallest(root, 1))

Java implementation

class TreeNode {
    int val;
    TreeNode left, right;
    TreeNode(int x) { val = x; }
}

public class Main {
    static int count = 0;
    static int result = -1;

    public static int kthSmallest(TreeNode root, int k) {
        inorder(root, k);
        return result;
    }

    private static void inorder(TreeNode node, int k) {
        if (node == null) return;
        inorder(node.left, k);
        count++;
        if (count == k) {
            result = node.val;
            return;
        }
        inorder(node.right, k);
    }

    public static void main(String[] args) {
        TreeNode root = new TreeNode(3);
        root.left = new TreeNode(1);
        root.right = new TreeNode(4);
        root.left.right = new TreeNode(2);
        System.out.println(kthSmallest(root, 1));
    }
}

JavaScript implementation

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

function kthSmallest(root, k) {
    let count = 0, result = null;
    function inorder(node) {
        if (!node || result !== null) return;
        inorder(node.left);
        count++;
        if (count === k) {
            result = node.val;
            return;
        }
        inorder(node.right);
    }
    inorder(root);
    return result;
}

const root = new TreeNode(3, new TreeNode(1, null, new TreeNode(2)), new TreeNode(4));
console.log(kthSmallest(root, 1));

Go implementation

package main

import (
    "fmt"
)

type TreeNode struct {
    Val   int
    Left  *TreeNode
    Right *TreeNode
}

var count int
var result int

func kthSmallest(root *TreeNode, k int) int {
    count = 0
    result = -1
    inorder(root, k)
    return result
}

func inorder(node *TreeNode, k int) {
    if node == nil {
        return
    }
    inorder(node.Left, k)
    count++
    if count == k {
        result = node.Val
        return
    }
    inorder(node.Right, k)
}

func main() {
    root := &TreeNode{3, &TreeNode{1, nil, &TreeNode{2, nil, nil}}, &TreeNode{4, nil, nil}}
    fmt.Println(kthSmallest(root, 1))
}

Rust implementation

struct TreeNode {
    val: i32,
    left: Option<Box<TreeNode>>,
    right: Option<Box<TreeNode>>,
}

impl TreeNode {
    fn new(val: i32) -> Self {
        TreeNode { val, left: None, right: None }
    }
}

fn inorder(node: &Option<Box<TreeNode>>, k: i32, count: &mut i32, result: &mut Option<i32>) {
    if let Some(n) = node {
        inorder(&n.left, k, count, result);
        *count += 1;
        if *count == k {
            *result = Some(n.val);
            return;
        }
        inorder(&n.right, k, count, result);
    }
}

fn kth_smallest(root: Option<Box<TreeNode>>, k: i32) -> i32 {
    let mut count = 0;
    let mut result = None;
    inorder(&root, k, &mut count, &mut result);
    result.unwrap()
}

fn main() {
    let root = Some(Box::new(TreeNode {
        val: 3,
        left: Some(Box::new(TreeNode {
            val: 1,
            left: None,
            right: Some(Box::new(TreeNode::new(2)),)
        })),
        right: Some(Box::new(TreeNode::new(4)),)
    }));

    println!("{}", kth_smallest(root, 1));
}

Kotlin implementation

class TreeNode(var `val`: Int) {
    var left: TreeNode? = null
    var right: TreeNode? = null
}

class Solution {
    private var count = 0
    private var result = -1

    fun kthSmallest(root: TreeNode?, k: Int): Int {
        inorder(root, k)
        return result
    }

    private fun inorder(node: TreeNode?, k: Int) {
        if (node == null) return
        inorder(node.left, k)
        count++
        if (count == k) {
            result = node.`val`
            return
        }
        inorder(node.right, k)
    }
}

fun main() {
    val root = TreeNode(3)
    root.left = TreeNode(1)
    root.right = TreeNode(4)
    root.left!!.right = TreeNode(2)
    val sol = Solution()
    println(sol.kthSmallest(root, 1))
}

Swift implementation

class TreeNode {
    var val: Int
    var left: TreeNode?
    var right: TreeNode?

    init(_ val: Int) {
        self.val = val
        self.left = nil
        self.right = nil
    }
}

class Solution {
    var count = 0
    var result: Int?

    func kthSmallest(_ root: TreeNode?, _ k: Int) -> Int {
        inorder(root, k)
        return result ?? -1
    }

    private func inorder(_ node: TreeNode?, _ k: Int) {
        guard let node = node else { return }
        inorder(node.left, k)
        count += 1
        if count == k {
            result = node.val
            return
        }
        inorder(node.right, k)
    }
}

let root = TreeNode(3)
root.left = TreeNode(1)
root.right = TreeNode(4)
root.left?.right = TreeNode(2)
let sol = Solution()
print(sol.kthSmallest(root, 1))

TypeScript implementation

class TreeNode {
    val: number;
    left: TreeNode | null;
    right: TreeNode | null;

    constructor(val: number, left: TreeNode | null = null, right: TreeNode | null = null) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

function kthSmallest(root: TreeNode | null, k: number): number {
    let count = 0;
    let result = -1;

    function inorder(node: TreeNode | null) {
        if (!node) return;
        inorder(node.left);
        count++;
        if (count === k) {
            result = node.val;
            return;
        }
        inorder(node.right);
    }

    inorder(root);
    return result;
}

const root = new TreeNode(3, new TreeNode(1, null, new TreeNode(2)), new TreeNode(4));
console.log(kthSmallest(root, 1));