Skip to main content

Kth Smallest Element in a BST


Kth Smallest Element in a BST: Given the root of a binary search tree, and an integer k, return the kth smallest value (1-indexed) of all the values of the nodes in the tree.

Example 1:

image

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

Example 2:

image

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

Constraints:
  • The number of nodes in the tree is n.
  • 1 <= k <= n <= 10^4
  • 0 <= Node.val <= 10^4

Try this Problem on your own or check similar problems:

  1. Binary Tree Inorder Traversal
  2. Second Minimum Node In a Binary Tree
Solution:
class Solution {
public int kthSmallest(TreeNode root, int k) {
Map<TreeNode, Integer> numberOfLeftChildren = new HashMap<>();
buildNumberofChildrenMaps(root, numberOfLeftChildren);
return helper(root, k, numberOfLeftChildren).val;
}

private int buildNumberofChildrenMaps(TreeNode root, Map<TreeNode, Integer> numberOfLeftChildren){
if(root == null) return 0;
if(root.left == null && root.right == null) return 1;

int left = buildNumberofChildrenMaps(root.left, numberOfLeftChildren);
int right = buildNumberofChildrenMaps(root.right, numberOfLeftChildren);

numberOfLeftChildren.put(root, left);

return left + right + 1;
}

private TreeNode helper(TreeNode root, int k, Map<TreeNode, Integer> numberOfLeftChildren){
if(k == numberOfLeftChildren.getOrDefault(root, 0) + 1) return root;

if(k < numberOfLeftChildren.getOrDefault(root, 0) + 1) return helper(root.left, k, numberOfLeftChildren);

return helper(root.right, k - numberOfLeftChildren.getOrDefault(root, 0) - 1, numberOfLeftChildren);
}
}

Time/Space Complexity:
  • Time Complexity: O(n)
  • Space Complexity: O(n)

Explanation:

It would be trivial to implement a solution which uses inorder traversal and decrements the counter until we reach count == 0 and just return the value at the node when the counter hits 0. We use wrapper class so we can pass the count and value by reference, and we iterate over until there is no left children left, and then go back to the root and traverse the right subtree.

class Solution {
public class ResultWrapper{
int count, value;
ResultWrapper(int count) {
this.count = count;
}
}
public int kthSmallest(TreeNode root, int k) {
ResultWrapper result = new ResultWrapper(k);
helper(root, result);
return result.value;
}

private void helper(TreeNode root, ResultWrapper result){
if(root.left != null) helper(root.left, result);
if(--result.count == 0){
result.value = root.val;
return;
}
if(root.right != null) helper(root.right, result);
}
}

The time and space complexity would be O(n) (space because of recursion stack, and time since we iterate over all nodes). But in the Solution section another approach is suggested which can be utilized if we're allowed to change the structure of BST class for future queries, for each node we would track the number of left children (in the solution we're doing this with helper data structure a map that tracks the number of left children for each of the nodes, we build the map using buildNumberofChildrenMaps). Then how do we use that information to find the kth smallest element? We traverse the tree and for each node we check if the number of left children is k-1 (in our code k == numberOfLeftChildren.getOrDefault(root, 0) + 1) and if it is we just return the value of the current node since it is the kth smallest element, otherwise we have two scenario. Current node is far from the kth smallest so we go deeper into the left subtree or current node is smaller than the kth smallest so we have to the right subtree (this time searching for k - x element, where x is the index of current node in sorted order).