Validate a Binary Search Tree
Problem
The tree is given in level order, with null for a missing child. Print true if it is a valid binary search tree: for every node, all values in the left subtree are smaller, and all values in the right subtree are bigger (all values are different).
Constraints
- 1 <= n <= 10^4 nodes
- Node values fit in 32 bits
Examples
Input
5 4 6 null null 3 7
Output
false
Solutions
A common mistake is to compare a node only with its parent. In the example, 3 is smaller than its parent 6, but it sits in the right subtree of 5. So each node must be checked against a range that shrinks as we go down.
/*
* Problem : Process a binary tree.
* Input : One line: the tree in level order, null for a missing child.
* Output : true or false.
* Approach: Pass down a value range.
* Time : O(n)
* Space : O(h)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
// Step 1: A tree node has a value and links to the left and right child. null means: no child.
static class TreeNode {
int value;
TreeNode left;
TreeNode right;
TreeNode(int value) {
this.value = value;
}
}
// This method builds a tree from the level order tokens. A queue keeps the nodes that still need children.
static TreeNode build(String[] tokens) {
if (tokens.length == 0 || tokens[0].equals("null")) {
return null;
}
TreeNode root = new TreeNode(Integer.parseInt(tokens[0]));
java.util.ArrayDeque<TreeNode> queue = new java.util.ArrayDeque<>();
queue.add(root);
int i = 1;
while (!queue.isEmpty() && i < tokens.length) {
TreeNode node = queue.poll();
if (i < tokens.length && !tokens[i].equals("null")) {
node.left = new TreeNode(Integer.parseInt(tokens[i]));
queue.add(node.left);
}
i++;
if (i < tokens.length && !tokens[i].equals("null")) {
node.right = new TreeNode(Integer.parseInt(tokens[i]));
queue.add(node.right);
}
i++;
}
return root;
}
// This method checks a subtree. All values in it must be bigger than "low" and smaller than "high".
static boolean isValid(TreeNode node, long low, long high) {
// Step 2: An empty subtree is valid.
if (node == null) {
return true;
}
// Step 3: The value must stay inside the allowed range. Comparing only with the parent is NOT enough.
if (node.value <= low || node.value >= high) {
return false;
}
// Step 4: The left subtree must be smaller than this node. The right subtree must be bigger.
return isValid(node.left, low, node.value) && isValid(node.right, node.value, high);
}
// This method solves the task. It receives the input and returns the answer.
static boolean solve(String s) {
return isValid(build(s.trim().split(" ")), Long.MIN_VALUE, Long.MAX_VALUE);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String s = scanner.hasNextLine() ? scanner.nextLine() : "";
System.out.println(solve(s));
}
}
Hints (1)
- What range must a node in the right subtree of 5 stay in?