K-th Smallest Value in a BST
Problem
The first line has distinct numbers. Insert them one by one into an empty binary search tree. The second line has the number k. Print the k-th smallest value in the tree (k = 1 is the smallest). Use an in-order walk (left, node, right) and stop as soon as you have counted k nodes.
Constraints
- 1 <= k <= n <= 1000
- values are distinct
Examples
Input
5 3 6 2 4 1 3
Output
3
Solutions
An in-order walk of a BST visits the values from small to big, so the k-th visited node is the answer. Stopping early means we do not need to visit the rest of the tree. Using an explicit stack avoids a deep recursion on long, thin trees.
/*
* Problem : Process a tree.
* Input : Line 1: values to insert. Line 2: the query.
* Output : The k-th smallest value.
* Approach: Build a BST, then walk in order.
* Time : O(h + k)
* Space : O(h)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
// Step 1: A node holds a value and two children. Smaller values go to the left, bigger values go to the right.
static class Node {
final long value;
Node left;
Node right;
Node(long value) {
this.value = value;
}
}
static Node insert(Node root, long value) {
if (root == null) {
return new Node(value);
}
if (value < root.value) {
root.left = insert(root.left, value);
} else {
root.right = insert(root.right, value);
}
return root;
}
// This method solves the task. It receives the input and returns the answer.
static long solve(String[] lines) {
Node root = null;
for (String text : lines[0].split(" ")) {
root = insert(root, Long.parseLong(text));
}
int k = Integer.parseInt(lines[1].trim());
// Step 2: An in-order walk without recursion: go left as far as possible and keep the nodes on a stack.
java.util.ArrayDeque<Node> stack = new java.util.ArrayDeque<>();
Node current = root;
int counted = 0;
while (current != null || !stack.isEmpty()) {
while (current != null) {
stack.push(current);
current = current.left;
}
// Step 3: The node on top of the stack is the next smallest value. Count it.
current = stack.pop();
counted++;
if (counted == k) {
return current.value;
}
// Step 4: After a node, visit its right subtree.
current = current.right;
}
return -1;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
java.util.List<String> all = new java.util.ArrayList<>();
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
if (!line.isEmpty()) {
all.add(line);
}
}
String[] lines = all.toArray(new String[0]);
System.out.println(solve(lines));
}
}
Hints (1)
- Why does an in-order walk give sorted values?