BST is a binary tree where left < root < right for all nodes. This ordering property enables O(log n) search.
Its core advantage:
BST search eliminates half the tree at each step — O(h) time, h = height.
Focus on recognizing:
“Sorted property” + “Left < root < right” + “Binary search” = BST
Pattern Table
| Pattern | Typical Questions | Trigger |
|---|---|---|
| Search / Insert | Find or add node | Compare value and go left/right |
| Validate BST | Is it a valid BST? | Range check (min, max) |
| Kth Smallest | Find Kth smallest element | Inorder traversal |
Mental Trigger
Compare value → Go left if smaller, right if larger → O(h).
1. Generic Java BST Template (Base)
class TreeNode {
int val;
TreeNode left, right;
TreeNode(int x) { val = x; }
}
public TreeNode search(TreeNode root, int key) {
if (root == null || root.val == key)
return root;
if (key < root.val)
return search(root.left, key);
return search(root.right, key);
}class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
def search(root, key):
if root is None or root.val == key:
return root
if key < root.val:
return search(root.left, key)
return search(root.right, key)struct TreeNode {
int val;
TreeNode *left, *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
TreeNode* search(TreeNode* root, int key) {
if (root == nullptr || root->val == key)
return root;
if (key < root->val)
return search(root->left, key);
return search(root->right, key);
}class TreeNode {
constructor(x) {
this.val = x;
this.left = null;
this.right = null;
}
}
function search(root, key) {
if (root === null || root.val === key)
return root;
if (key < root.val)
return search(root.left, key);
return search(root.right, key);
}Everything else in BST is just a modification of this template.
Pattern 1: Insert into BST
Comparisons walk you down; the first empty slot is your leaf. Press ▶ to animate.
⚠️ Animation & Content Notice
The animation work is not fully finished — some animations may have slight errors.
If there is a major error in the content or if the animation or content is difficult to understand, please contact us at rayyancodingschool@gmail.com.
BST Insert
Insert a value into a BST by walking comparisons and attaching a leaf.
Start at the root; go left if smaller, right if larger, until an empty child slot is found, then attach the new node there. Inserts are always leaves, so plain BST insert needs no rebalancing.
1
walk from root:
2
val < node → go left
3
val > node → go right
4
attach at empty slot
Java Code
public TreeNode insert(TreeNode root, int val) {
if (root == null)
return new TreeNode(val);
if (val < root.val)
root.left = insert(root.left, val);
else if (val > root.val)
root.right = insert(root.right, val);
return root;
}def insert(root, val):
if root is None:
return TreeNode(val)
if val < root.val:
root.left = insert(root.left, val)
elif val > root.val:
root.right = insert(root.right, val)
return rootTreeNode* insert(TreeNode* root, int val) {
if (root == nullptr)
return new TreeNode(val);
if (val < root->val)
root->left = insert(root->left, val);
else if (val > root->val)
root->right = insert(root->right, val);
return root;
}function insert(root, val) {
if (root === null)
return new TreeNode(val);
if (val < root.val)
root.left = insert(root.left, val);
else if (val > root.val)
root.right = insert(root.right, val);
return root;
}What Changed from the Base Template?
Create node on null
Base:
if (root == null || root.val == key) return root;
Changed:
if (root == null) return new TreeNode(val);
because insertion creates a new node when it reaches a null position.
Insert = Search + Create node at null position.
Pattern 2: Validate BST
Min/max bounds travel down the tree — local checks aren’t enough. Press ▶ to animate.
⚠️ Animation & Content Notice
The animation work is not fully finished — some animations may have slight errors.
If there is a major error in the content or if the animation or content is difficult to understand, please contact us at rayyancodingschool@gmail.com.
Validate Binary Search Tree
Confirm a tree is a BST where every node lies strictly between inherited min/max bounds.
Recurse with a (lo, hi) window; each node must be inside its ancestors' bounds. A naive 'left<me<right' check misses violations that appear only against higher ancestors — bounds must travel down.
1
valid(node, lo, hi):
2
node in (lo, hi)?
3
left = valid(node.l, lo, node.val)
4
right = valid(node.r, node.val, hi)
Java Code
public boolean isValidBST(TreeNode root) {
return validate(root, null, null);
}
private boolean validate(TreeNode root, Integer min, Integer max) {
if (root == null) return true;
if ((min != null && root.val <= min) ||
(max != null && root.val >= max))
return false;
return validate(root.left, min, root.val)
&& validate(root.right, root.val, max);
}def is_valid_bst(root):
return validate(root, None, None)
def validate(root, min_val, max_val):
if root is None:
return True
if (min_val is not None and root.val <= min_val) or \
(max_val is not None and root.val >= max_val):
return False
return validate(root.left, min_val, root.val) and \
validate(root.right, root.val, max_val)bool isValidBST(TreeNode* root) {
return validate(root, LLONG_MIN, LLONG_MAX);
}
bool validate(TreeNode* root, long long minVal, long long maxVal) {
if (root == nullptr) return true;
if (root->val <= minVal || root->val >= maxVal)
return false;
return validate(root->left, minVal, root->val)
&& validate(root->right, root->val, maxVal);
}function isValidBST(root) {
return validate(root, null, null);
}
function validate(root, min, max) {
if (root === null) return true;
if ((min !== null && root.val <= min) ||
(max !== null && root.val >= max))
return false;
return validate(root.left, min, root.val)
&& validate(root.right, root.val, max);
}What Changed from the Base Template?
Range tracking
Base:
// just search for value
Changed:
Integer min, Integer max
because validation requires that all nodes in the left subtree are < root and all in the right subtree are > root.
Recursive range narrowing
Added:
validate(root.left, min, root.val) // upper bound = current root
validate(root.right, root.val, max) // lower bound = current root
to propagate the allowed range as we descend.
Validate BST = DFS with (min, max) range — left narrows max, right narrows min.
Pattern 3: Kth Smallest Element
Inorder = sorted order; just count pops until k. Press ▶ to animate.
⚠️ Animation & Content Notice
The animation work is not fully finished — some animations may have slight errors.
If there is a major error in the content or if the animation or content is difficult to understand, please contact us at rayyancodingschool@gmail.com.
Kth Smallest In A BST
Find the k-th smallest element of a BST using iterative inorder.
Because inorder of a BST is sorted, push the left spine, pop-visit while counting, and stop when the counter reaches k. Each pop hands back the next-larger node.
1
stack = []; cur = root
2
while stack or cur:
3
push left spine; cur = left
4
cur = pop(); count++
5
if count == k → answer
6
cur = cur.right
Java Code
public int kthSmallest(TreeNode root, int k) {
Stack<TreeNode> stack = new Stack<>();
TreeNode curr = root;
while (curr != null || !stack.isEmpty()) {
while (curr != null) {
stack.push(curr);
curr = curr.left;
}
curr = stack.pop();
k--;
if (k == 0) return curr.val;
curr = curr.right;
}
return -1;
}def kth_smallest(root, k):
stack = []
curr = root
while curr is not None or stack:
while curr is not None:
stack.append(curr)
curr = curr.left
curr = stack.pop()
k -= 1
if k == 0:
return curr.val
curr = curr.right
return -1int kthSmallest(TreeNode* root, int k) {
stack<TreeNode*> st;
TreeNode* curr = root;
while (curr != nullptr || !st.empty()) {
while (curr != nullptr) {
st.push(curr);
curr = curr->left;
}
curr = st.top();
st.pop();
k--;
if (k == 0) return curr->val;
curr = curr->right;
}
return -1;
}function kthSmallest(root, k) {
const stack = [];
let curr = root;
while (curr !== null || stack.length > 0) {
while (curr !== null) {
stack.push(curr);
curr = curr.left;
}
curr = stack.pop();
k--;
if (k === 0) return curr.val;
curr = curr.right;
}
return -1;
}What Changed from the Base Template?
Count during inorder
Base:
// collect all or search for value
Changed:
k--;
if (k == 0) return curr.val;
because inorder traversal of BST produces sorted order — the Kth visited node is the Kth smallest.
Kth Smallest = Inorder traversal + Stop at Kth visited node.
BST Pattern Evolution
BST Search (compare + go left/right)
↓
Insert
(+ create node at null position)
↓
Validate
(+ range bounds narrowing)
↓
Kth Smallest
(+ inorder traversal + count)
Common Mistakes
Not handling duplicates in validation.
root.val <= min and root.val >= max — BST typically excludes duplicates.
Forgetting BST property in insertion.
Equal values: skip or handle based on problem specification.
Using recursion for large unbalanced trees.
Stack overflow possible — use iterative stack or Morris traversal.
Recognition Cheat Sheet
| If you see… | Think… |
|---|---|
| Sorted tree property | BST |
| Insert into BST | Search + create |
| Validate BST | Range check (min, max) |
| Kth smallest/largest | Inorder + count |
| Search in BST | Compare + go left/right |
Premium Content
Unlock Binary Search Tree and all premium lessons with a subscription.
From ₹199.99/year — See plans