A tree is a non-linear hierarchical data structure used to represent relationships.
Unlike arrays or linked lists, trees allow multiple paths, branching, and hierarchy, making them ideal for modeling real-world systems.
Examples:
A binary tree is a tree in which:
Node structure:
class TreeNode {
int val;
TreeNode left, right;
}
Understanding terminology avoids confusion later.
Traversal means visiting every node exactly once.
Explores deep before wide.
Used in BST to get sorted order.
void inorder(TreeNode root){
if(root == null) return;
inorder(root.left);
System.out.print(root.val);
inorder(root.right);
}
Used in tree construction & serialization.
void preorder(TreeNode root){
if(root == null) return;
System.out.print(root.val);
preorder(root.left);
preorder(root.right);
}
Used in deletion and bottom-up problems.
void postorder(TreeNode root){
if(root == null) return;
postorder(root.left);
postorder(root.right);
System.out.print(root.val);
}
Traverses level by level using a queue.
void levelOrder(TreeNode root){
Queue<TreeNode> q = new LinkedList<>();
q.add(root);
while(!q.isEmpty()){
TreeNode curr = q.poll();
System.out.print(curr.val);
if(curr.left != null) q.add(curr.left);
if(curr.right != null) q.add(curr.right);
}
}
int height(TreeNode root){
if(root == null) return 0;
return 1 + Math.max(height(root.left), height(root.right));
}
The longest path between any two nodes.
May or may not pass through root.
Calculate height and update diameter simultaneously.
int diameter = 0;
int height(TreeNode root){
if(root == null) return 0;
int lh = height(root.left);
int rh = height(root.right);
diameter = Math.max(diameter, lh + rh);
return 1 + Math.max(lh, rh);
}
A tree is balanced if:
|height(left) − height(right)| ≤ 1
for every node.
boolean isBalanced(TreeNode root){
return check(root) != -1;
}
int check(TreeNode root){
if(root == null) return 0;
int lh = check(root.left);
if(lh == -1) return -1;
int rh = check(root.right);
if(rh == -1) return -1;
if(Math.abs(lh - rh) > 1) return -1;
return 1 + Math.max(lh, rh);
}
The deepest node that is ancestor of both nodes.
TreeNode lca(TreeNode root, int p, int q){
if(root == null || root.val == p || root.val == q)
return root;
TreeNode left = lca(root.left, p, q);
TreeNode right = lca(root.right, p, q);
if(left != null && right != null)
return root;
return left != null ? left : right;
}
Check if a root-to-leaf path equals target sum.
boolean hasPathSum(TreeNode root, int sum){
if(root == null) return false;
if(root.left == null && root.right == null)
return sum == root.val;
return hasPathSum(root.left, sum - root.val) ||
hasPathSum(root.right, sum - root.val);
}
Variants include:
To store or transmit trees.
void serialize(TreeNode root, StringBuilder sb){
if(root == null){
sb.append("null,");
return;
}
sb.append(root.val).append(",");
serialize(root.left, sb);
serialize(root.right, sb);
}
TreeNode deserialize(Queue<String> q){
String val = q.poll();
if(val.equals("null")) return null;
TreeNode node = new TreeNode(Integer.parseInt(val));
node.left = deserialize(q);
node.right = deserialize(q);
return node;
}
A BST is a binary tree where:
Left < Root < Right
This property enables logarithmic search.
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);
}
TreeNode insert(TreeNode root, int val){
if(root == null) return new TreeNode(val);
if(val < root.val)
root.left = insert(root.left, val);
else
root.right = insert(root.right, val);
return root;
}
boolean isValid(TreeNode root){
return validate(root, Long.MIN_VALUE, Long.MAX_VALUE);
}
boolean validate(TreeNode root, long min, long max){
if(root == null) return true;
if(root.val <= min || root.val >= max)
return false;
return validate(root.left, min, root.val) &&
validate(root.right, root.val, max);
}
Inorder traversal gives sorted order.
int count = 0;
int ans;
void inorder(TreeNode root, int k){
if(root == null) return;
inorder(root.left, k);
count++;
if(count == k) ans = root.val;
inorder(root.right, k);
}
int floor(TreeNode root, int key){
int res = -1;
while(root != null){
if(root.val == key) return root.val;
if(root.val < key){
res = root.val;
root = root.right;
} else {
root = root.left;
}
}
return res;
}
Creates a height-balanced BST.
TreeNode build(int[] arr, int l, int r){
if(l > r) return null;
int mid = (l + r) / 2;
TreeNode root = new TreeNode(arr[mid]);
root.left = build(arr, l, mid - 1);
root.right = build(arr, mid + 1, r);
return root;
}