Master Every Topic,
Ace the Lab Exam.
Complete prep guide covering all 5 syllabus topics: Arrays, Strings, Linked List, Stack & Queue, and Trees β with Java code, dry-run traces, and quizzes.
β Your Readiness Tracker
0/0 topics ready
π¦ Arrays
Traversal, Insertion, Deletion, Linear & Binary Search, Bubble & Selection Sort, Sliding Window.
π€ Strings
String & character functions, traversal, palindrome, anagram, reverse, vowels.
π Linked List
Singly, Doubly, Circular LL β insert at beginning/end, delete first/last, count nodes.
π Stack & Queue
Push/Pop/Peek, InfixβPostfix, Postfix eval, Enqueue/Dequeue, Circular Queue, Deque.
π³ Trees
Binary Tree, BST, Preorder/Inorder/Postorder, Height, Count Nodes, Same Tree.
π§ Quiz
Topic-wise MCQs covering all 5 units. Instant feedback and explanations.
πExam Pattern Reminder
50 MCQs
Covers all 5 topics. Each question tests concept, code output, or complexity. Time budget: ~60 min.
2 Easy Coding Qs
Array/String/LL basics. Direct implementation. Time budget: ~20 min each.
1 Medium Coding Q
Stack application, Tree traversal, or Sliding Window. Time budget: ~20 min.
Language: Java
BYOD β bring your own device. Use Scanner for input. Always write Time & Space complexity.
π¦Array Basics & Traversal
An array stores elements of the same type in contiguous memory. Index starts at 0.
import java.util.Scanner; public class ArrayBasics { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[] arr = new int[n]; // Input for (int i = 0; i < n; i++) arr[i] = sc.nextInt(); // Reverse an Array int left = 0, right = n - 1; while (left < right) { int temp = arr[left]; arr[left++] = arr[right]; arr[right--] = temp; } // Print for (int x : arr) System.out.print(x + " "); } }
πLinear & Binary Search
int linearSearch(int[] arr, int target) { for (int i = 0; i < arr.length; i++) if (arr[i] == target) return i; return -1; // not found } // Time: O(n) | Space: O(1)
int binarySearch(int[] arr, int target) { int left = 0, right = arr.length - 1; while (left <= right) { int mid = left + (right - left) / 2; // safe mid if (arr[mid] == target) return mid; else if (arr[mid] < target) left = mid + 1; else right = mid - 1; } return -1; } // Time: O(log n) | Space: O(1)
πBubble Sort & Selection Sort
void bubbleSort(int[] arr) { int n = arr.length; for (int i = 0; i < n - 1; i++) { for (int j = 0; j < n - i - 1; j++) { if (arr[j] > arr[j + 1]) { int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; // swap } } } } // Time: O(nΒ²) | Space: O(1)
void selectionSort(int[] arr) { int n = arr.length; for (int i = 0; i < n - 1; i++) { int minIdx = i; for (int j = i + 1; j < n; j++) if (arr[j] < arr[minIdx]) minIdx = j; // swap arr[i] with arr[minIdx] int temp = arr[minIdx]; arr[minIdx] = arr[i]; arr[i] = temp; } } // Time: O(nΒ²) | Space: O(1)
Bubble Sort: compares adjacent elements, bubbles max to end each pass.
Selection Sort: finds minimum in unsorted part, places it at beginning.
ππTwo Pointer Technique
Use two pointers from opposite ends or moving together to solve array problems in O(n).
int[] twoSum(int[] arr, int target) { int left = 0, right = arr.length - 1; while (left < right) { int sum = arr[left] + arr[right]; if (sum == target) return new int[]{left, right}; else if (sum < target) left++; else right--; } return new int[]{-1, -1}; } // Time: O(n) | Space: O(1)
void moveZeroes(int[] arr) { int j = 0; // pointer for next non-zero position for (int i = 0; i < arr.length; i++) if (arr[i] != 0) arr[j++] = arr[i]; while (j < arr.length) arr[j++] = 0; } // Time: O(n) | Space: O(1)
int removeDuplicates(int[] arr) { if (arr.length == 0) return 0; int j = 1; for (int i = 1; i < arr.length; i++) if (arr[i] != arr[i - 1]) arr[j++] = arr[i]; return j; // new length } // Time: O(n) | Space: O(1)
πͺSliding Window of Size K β
Fix window size K. Slide it across the array. Track sum/max. Avoids O(nΒ·k) brute force.
void slidingWindow(int[] arr, int k) { int n = arr.length; if (n < k) { System.out.println("Invalid"); return; } int windowSum = 0; // Build first window for (int i = 0; i < k; i++) windowSum += arr[i]; int maxSum = windowSum; // Slide window for (int i = k; i < n; i++) { windowSum += arr[i] - arr[i - k]; // add new, remove old maxSum = Math.max(maxSum, windowSum); System.out.println("Window ["+(i-k+1)+","+i+"] Sum="+windowSum); } System.out.println("Max Sum = " + maxSum); } // Time: O(n) | Space: O(1)
πAll Practice Problems (Quick Reference)
1. Reverse an Array β two pointer swap
2. Check if Array is Palindrome β compare left & right
3. Two Sum II (Sorted Array) β two pointers
4. Remove Duplicates from Sorted Array β two pointers
5. Move Zeroes β partition technique
6. Sum of Subarray of Size K β sliding window
7. Average of Subarray of Size K β sum / k each slide
8. Maximum Element in Subarray of Size K β track max
9. Count Subarrays of Size K β n - k + 1
10. Find All Anagrams in a String β frequency map + sliding window
// Number of subarrays of exactly size k = n - k + 1 int countSubarrays(int n, int k) { return n >= k ? n - k + 1 : 0; }
π€String Basics in Java
Strings are immutable in Java. Use StringBuilder for efficient modification.
String s = "Hello World"; s.length(); // 11 s.charAt(0); // 'H' s.toUpperCase(); // "HELLO WORLD" s.toLowerCase(); // "hello world" s.substring(6); // "World" s.substring(0,5); // "Hello" s.trim(); // removes leading/trailing spaces s.replace('l','x'); // "Hexxo Worxd" s.contains("World");// true s.split(" "); // ["Hello","World"] s.toCharArray(); // char array // Character utility methods Character.isLetter('a'); // true Character.isDigit('3'); // true Character.isUpperCase('A'); // true Character.toLowerCase('A');// 'a'
πReverse a String & Check Palindrome
String reverse(String s) { return new StringBuilder(s).reverse().toString(); } // Manual approach: String reverseManual(String s) { char[] ch = s.toCharArray(); int l = 0, r = ch.length - 1; while (l < r) { char temp = ch[l]; ch[l++] = ch[r]; ch[r--] = temp; } return new String(ch); }
boolean isPalindrome(String s) { int l = 0, r = s.length() - 1; while (l < r) { if (s.charAt(l++) != s.charAt(r--)) return false; } return true; }
π‘Count Vowels, Reverse Vowels, Count Occurrence
void countVC(String s) { s = s.toLowerCase(); int vowels = 0, consonants = 0; for (char c : s.toCharArray()) { if ("aeiou".indexOf(c) >= 0) vowels++; else if (Character.isLetter(c)) consonants++; } System.out.println("Vowels: "+vowels+", Consonants: "+consonants); }
String reverseVowels(String s) { char[] ch = s.toCharArray(); int l = 0, r = ch.length - 1; String vowels = "aeiouAEIOU"; while (l < r) { while (l < r && vowels.indexOf(ch[l]) < 0) l++; while (l < r && vowels.indexOf(ch[r]) < 0) r--; char tmp = ch[l]; ch[l++] = ch[r]; ch[r--] = tmp; } return new String(ch); }
int countOccurrence(String s, char target) { int count = 0; for (char c : s.toCharArray()) if (c == target) count++; return count; } String removeSpaces(String s) { return s.replace(" ", ""); // or: s.replaceAll("\\s+", "") }
πReverse Each Word of String
String reverseEachWord(String s) { String[] words = s.trim().split("\\s+"); StringBuilder sb = new StringBuilder(); for (String w : words) { sb.append(new StringBuilder(w).reverse()).append(' '); } return sb.toString().trim(); } // "hello world" β "olleh dlrow"
πAnagram Check (Find All Anagrams)
Two strings are anagrams if they have the same character frequencies.
boolean isAnagram(String s, String t) { if (s.length() != t.length()) return false; int[] freq = new int[26]; for (int i = 0; i < s.length(); i++) { freq[s.charAt(i) - 'a']++; freq[t.charAt(i) - 'a']--; } for (int f : freq) if (f != 0) return false; return true; } // Time: O(n) | Space: O(1)
πLinked List Node Structure
class Node { int data; Node next; Node(int data) { this.data = data; this.next = null; } } class LinkedList { Node head = null; // Traverse and print void display() { Node curr = head; while (curr != null) { System.out.print(curr.data + " β "); curr = curr.next; } System.out.println("null"); } }
1. Always check null before accessing .next or .data
2. Save the next pointer before modifying links
3. Draw the list on paper before writing code
βInsert at Beginning & End
void insertAtBeginning(int data) { Node newNode = new Node(data); newNode.next = head; // point to old head head = newNode; // update head } // Time: O(1)
void insertAtEnd(int data) { Node newNode = new Node(data); if (head == null) { head = newNode; return; } Node curr = head; while (curr.next != null) curr = curr.next; curr.next = newNode; // link last node to new } // Time: O(n)
βDelete First & Last Node
void deleteFirst() { if (head == null) { System.out.println("Empty list"); return; } head = head.next; // move head forward } // Time: O(1)
void deleteLast() { if (head == null) return; if (head.next == null) { head = null; return; } // only 1 node Node curr = head; while (curr.next.next != null) curr = curr.next; curr.next = null; // disconnect last node } // Time: O(n)
π’Count Number of Nodes
int countNodes() { int count = 0; Node curr = head; while (curr != null) { count++; curr = curr.next; } return count; } // Time: O(n) | Space: O(1)
βοΈDoubly Linked List
Each node has both next and prev pointers.
class DNode { int data; DNode next, prev; DNode(int data) { this.data = data; } } // Insert at beginning of DLL DNode insertFront(DNode head, int data) { DNode node = new DNode(data); node.next = head; if (head != null) head.prev = node; return node; // new head } // Delete a node in DLL void deleteNode(DNode node) { if (node.prev != null) node.prev.next = node.next; if (node.next != null) node.next.prev = node.prev; }
πCircular Linked List
Last node points back to head. No null at end.
// Insert at end of Circular LL Node insertCircular(Node head, int data) { Node node = new Node(data); if (head == null) { node.next = node; return node; } Node curr = head; while (curr.next != head) curr = curr.next; curr.next = node; node.next = head; // circular link return head; } // Traverse Circular LL void displayCircular(Node head) { if (head == null) return; Node curr = head; do { System.out.print(curr.data + " β "); curr = curr.next; } while (curr != head); System.out.println("(back to head)"); }
do-while loop for circular LL traversal to ensure head is visited!πStack β Array Based Implementation
LIFO: Last In, First Out. Top tracks the latest element.
class Stack { int[] arr; int top = -1; int capacity; Stack(int size) { arr = new int[size]; capacity = size; } void push(int val) { if (top == capacity - 1) { System.out.println("Stack Overflow"); return; } arr[++top] = val; } int pop() { if (top == -1) { System.out.println("Stack Underflow"); return -1; } return arr[top--]; } int peek() { if (top == -1) return -1; return arr[top]; } boolean isEmpty() { return top == -1; } boolean isFull() { return top == capacity - 1; } }
β Valid Parentheses β (Most Important Stack Q)
boolean isValid(String s) { Stack<Character> stack = new Stack<>(); for (char c : s.toCharArray()) { if (c == '(' || c == '[' || c == '{') stack.push(c); else { if (stack.isEmpty()) return false; char top = stack.pop(); if (c == ')' && top != '(') return false; if (c == ']' && top != '[') return false; if (c == '}' && top != '{') return false; } } return stack.isEmpty(); // must be empty at end }
πNext Greater Element
For each element, find the first element to its right that is greater. Use monotonic stack.
int[] nextGreater(int[] arr) { int n = arr.length; int[] result = new int[n]; Arrays.fill(result, -1); // default: no greater element Deque<Integer> stack = new ArrayDeque<>(); for (int i = 0; i < n; i++) { // Pop elements smaller than current while (!stack.isEmpty() && arr[stack.peek()] < arr[i]) result[stack.pop()] = arr[i]; stack.push(i); } return result; } // Time: O(n) | Space: O(n)
NGE: [5, 10, 10, -1, -1]
πInfix to Postfix Conversion
Convert a+b*c β abc*+. Use operator precedence and stack.
int prec(char op) { if (op == '+' || op == '-') return 1; if (op == '*' || op == '/') return 2; return 0; } String infixToPostfix(String exp) { StringBuilder result = new StringBuilder(); Stack<Character> stack = new Stack<>(); for (char c : exp.toCharArray()) { if (Character.isLetterOrDigit(c)) { result.append(c); } else if (c == '(') { stack.push(c); } else if (c == ')') { while (!stack.isEmpty() && stack.peek() != '(') result.append(stack.pop()); stack.pop(); // remove '(' } else { // operator while (!stack.isEmpty() && prec(stack.peek()) >= prec(c)) result.append(stack.pop()); stack.push(c); } } while (!stack.isEmpty()) result.append(stack.pop()); return result.toString(); } // "a+b*c" β "abc*+"
πΆQueue β Array Based (FIFO)
class Queue { int[] arr; int front = 0, rear = -1, size = 0, capacity; Queue(int cap) { arr = new int[cap]; capacity = cap; } void enqueue(int val) { if (size == capacity) { System.out.println("Queue Full"); return; } rear = (rear + 1) % capacity; arr[rear] = val; size++; } int dequeue() { if (size == 0) { System.out.println("Queue Empty"); return -1; } int val = arr[front]; front = (front + 1) % capacity; size--; return val; } boolean isEmpty() { return size == 0; } }
πCircular Queue & Deque
Circular Queue reuses empty spaces. The Queue above already uses circular indexing with (rear+1) % capacity.
// Java's built-in Deque β use in exams! Deque<Integer> dq = new ArrayDeque<>(); dq.addFirst(1); // add to front dq.addLast(2); // add to rear dq.removeFirst(); // remove from front dq.removeLast(); // remove from rear dq.peekFirst(); // view front without removing dq.peekLast(); // view rear without removing
Circular Queue advantage: rear wraps around, reuses freed front slots β no wasted space.
Deque: can add/remove from both ends, O(1) per operation.
π³Binary Tree β Node Structure
class TreeNode { int val; TreeNode left, right; TreeNode(int val) { this.val = val; left = right = null; } } // Build a sample tree: // 1 // / \ // 2 3 // / \ // 4 5 TreeNode root = new TreeNode(1); root.left = new TreeNode(2); root.right = new TreeNode(3); root.left.left = new TreeNode(4); root.left.right = new TreeNode(5);
Root: topmost node | Leaf: node with no children | Height: longest path rootβleaf
BST property: left < node < right (for all nodes)
β©οΈInorder Traversal (Left β Root β Right)
For a BST, inorder traversal gives elements in sorted order.
void inorder(TreeNode root) { if (root == null) return; // base case inorder(root.left); // visit left System.out.print(root.val + " "); // visit root inorder(root.right); // visit right }
β‘οΈPreorder Traversal (Root β Left β Right)
Root is processed first. Used to copy/clone a tree.
void preorder(TreeNode root) { if (root == null) return; System.out.print(root.val + " "); // visit root FIRST preorder(root.left); preorder(root.right); } // Same tree β Output: 1 2 4 5 3
β¬ οΈPostorder Traversal (Left β Right β Root)
Root is processed last. Used to delete a tree or evaluate expression trees.
void postorder(TreeNode root) { if (root == null) return; postorder(root.left); postorder(root.right); System.out.print(root.val + " "); // visit root LAST } // Same tree β Output: 4 5 2 3 1
Tree: 1, left=2(children:4,5), right=3
Inorder: 4 2 5 1 3 | Preorder: 1 2 4 5 3 | Postorder: 4 5 2 3 1
πHeight & Count Nodes
int height(TreeNode root) { if (root == null) return 0; // base: null has height 0 int leftH = height(root.left); int rightH = height(root.right); return 1 + Math.max(leftH, rightH); } // Time: O(n)
int countNodes(TreeNode root) { if (root == null) return 0; return 1 + countNodes(root.left) + countNodes(root.right); } // Time: O(n) | Space: O(h) β h = height
πSame Tree & BST Basics
boolean isSameTree(TreeNode p, TreeNode q) { if (p == null && q == null) return true; // both null if (p == null || q == null) return false; // one null if (p.val != q.val) return false; // values differ return isSameTree(p.left, q.left) && isSameTree(p.right, q.right); }
// BST Search boolean searchBST(TreeNode root, int key) { if (root == null) return false; if (root.val == key) return true; if (key < root.val) return searchBST(root.left, key); return searchBST(root.right, key); } // Time: O(h) β O(log n) for balanced BST // BST Insert TreeNode insertBST(TreeNode root, int val) { if (root == null) return new TreeNode(val); if (val < root.val) root.left = insertBST(root.left, val); else root.right = insertBST(root.right, val); return root; }
π§ MCQ Quiz β All Topics
Click an option. Get instant feedback. Reset to try again.
π¦ Arrays
π¦ Arrays
π¦ Arrays
π€ Strings
π€ Strings
π Linked List
π Linked List
π Linked List
π Stack & Queue
π Stack & Queue
π Stack & Queue
π³ Trees
π³ Trees
π³ Trees
π³ Trees
πQuick Reference Cheatsheet
All 5 topics at a glance β print this before entering the exam hall.
β± Time Complexities
π― Pattern Recognition
π Linked List Tricks
π³ Tree Traversal Order
π¦ Array Quick Ops
π Exam Day Tips
πImportant Notes from Syllabus
Focus on traversal order
Memorize In/Pre/Post order. Know which gives sorted output (Inorder in BST).
Dry run before coding
Always trace through an example manually before writing any code.
Practice recursion base case
Every recursive tree function starts with: if (root == null) return 0/false/null.
Understand node visiting sequence
Draw the tree and number each step of the traversal on paper.