Java · Practice

Coding Drills

100 hands-on Java problems, organised into 10 topics that build on each other. Each drill has the problem, the key insight, a step-by-step diagram, a complete compilable solution, complexity, and the bugs people usually write.

100
Drills
10
Topics
25+
Patterns
Drills vs. LeetCode sets: these drills are about writing the logic yourself: loops, pointers, recursion, and the core techniques. For interview-style write-ups grouped by pattern, see the LeetCode Problem Sets. For the theory behind each structure, see the DSA Guide.
01
Section One · Roadmap

How the 10 Topics Build on Each Other

The order matters. Arrays and hashing teach you to trade memory for time. Two pointers and sliding window teach you to stop re-scanning data. Binary search teaches you to throw half the input away. Linked lists drill pointer handling, which trees then use recursively. Grids and graphs reuse the same DFS and BFS on a wider structure. Dynamic programming caches those recursions, and backtracking enumerates them. Work top to bottom the first time; after that, jump straight to whichever topic you're weakest in.

Learning path — 10 topics, 100 drills
LINEAR STRUCTURES · drills 1–50 01 Arrays & Hashing · 1–12 02 Two Pointers 13–23 03 Sliding Window 24–32 04 Binary Search 33–39 05 Linked Lists 40–50 06 Trees & BST 51–64 07 Grids 65–71 08 Graphs 72–80 09 Dynamic Prog. 81–94 10 Backtracking & Design 95–100 NON-LINEAR · drills 51–100 pointer skills (05) → recursion on trees (06) → DFS/BFS on grids & graphs (07–08) → cache the recursion (09) → enumerate the recursion (10) click any box to open the topic
Analogy: It works like learning an instrument. Scales come first (arrays, pointers), then chords (trees, graphs), then improvisation (DP, backtracking). Skip the scales and the improvisation sounds like noise: most DP bugs are really off-by-one array bugs, and most graph bugs are really pointer bugs.
02
Section Two · Topics

The 10 Topic Pages

Part 1 · Linear Structures (Drills 1–50)
Part 2 · Trees, Graphs & DP (Drills 51–100)
03
Section Three · Method

How to Work Every Drill

Every drill page follows the same six steps, and your own practice should too. The most common mistake is jumping straight to code. A few minutes on examples and a brute force almost always reveal the optimal pattern, because the optimal solution is usually the brute force with one repeated piece of work removed.

The six-step drill loop
1 · UNDERSTAND inputs, outputs, constraints on n 2 · EXAMPLES trace by hand, add an edge case 3 · BRUTE simplest correct idea + its Big-O 4 · OPTIMIZE find repeated work, pick a pattern 5 · CODE name invariants, small helpers 6 · TEST empty, single, dupes, max n test fails → revisit the idea, not just the code Optimal = brute force − repeated work re-scanning → pointers/window · re-searching → hash/binary search · re-computing → DP memo
Brute force re-scans a range for every start index
▶
Keep a window or two pointers that only move forward, so each element is visited O(1) times: O(n²) → O(n)
Brute force searches the array for a value you've already seen
▶
Store seen values in a HashMap/HashSet so each lookup is O(1): O(n²) → O(n) time, at the cost of O(n) space
Input is sorted, or the answer is monotonic (too small / big enough)
▶
Binary search on the index or on the answer: O(n) → O(log n) per query
The recursion tree solves the same sub-problem many times
▶
Memoize or build a bottom-up table: exponential → polynomial
You repeatedly need the current min/max of a changing set
▶
Use a heap (PriorityQueue) or a monotonic stack/deque: O(n) per query → O(log n) or amortised O(1)
04
Section Four · Recognition

Pattern Finder: From Problem Signal to Technique

Most drills give away their pattern in the problem statement. Train yourself to spot these signals in the first read. Each row links the signal to the technique and to the page that drills it.

Signal → pattern → topic page
IF THE PROBLEM SAYS… REACH FOR… PAGE "seen before", "count", "find the pair" HashMap / HashSet 01 "subarray sums to k", "range total" Prefix sum + HashMap 01 "sorted array", "in-place", "pair/triplet" Two pointers 02 "longest/shortest substring with…" Sliding window + freq map 03 "sorted / rotated", "O(log n)", "minimum k such that" Binary search (index or answer) 04 "cycle", "middle", "k-th from end" (list) Fast/slow + dummy head 05 "root", "subtree", "depth", "level by level" Recursive DFS / BFS queue 06 "m×n grid", "islands", "spreads each minute" Grid DFS / multi-source BFS 07 "prerequisites", "connected", "cheapest" Topo sort / Union-Find / Dijkstra 08 "number of ways", "min cost", "can you reach" DP (1D / 2D / knapsack) 09 "return all permutations / combinations" → Backtracking · "design a cache / stack" → HashMap + DLL → 10
Trap: "sorted" doesn't always mean binary search, and "substring" doesn't always mean sliding window. Sliding window needs a condition that stays valid (or invalid) as the window shrinks. Longest Palindromic Substring has no such condition, which is why it uses expand-around-center instead (drill 28).
05
Section Five · Budget

Read the Constraints: Your Complexity Budget

A typical judge runs roughly 108 simple operations per second. The constraint on n tells you which complexity is acceptable, and that in turn narrows down which patterns are even worth trying.

Max nTargetTypical techniqueExample drills
n ≤ 10O(n!)Permutations, full backtracking95 Permutations
n ≤ 20–25O(2n)Subsets, combination search96 Combination Sum, 97 Parentheses
n ≤ 500O(n³)Interval DP, triple loops93 Longest Palindromic Subseq. (n²)
n ≤ 104O(n²)2D DP, expand-around-center28 Palindrome, 86 LIS (n² version), 94 Edit Distance
n ≤ 106O(n log n)Sort, heap, binary search38 Merge Intervals, 79 Kruskal, 100 K Closest
n ≤ 108O(n)Hashing, two pointers, window1 Two Sum, 21 Rain Water, 27 Min Window
n > 108O(log n) / O(1)Binary search, math33 Search Insert, 37 Median (log)
Relative growth of common complexities (illustrative)
input size n → operations → O(2ⁿ) O(n²) O(n log n) O(n) O(log n) O(1)
06
Section Six · Toolkit

The Java You'll Type Most

Most of the 100 solutions use the same dozen or so API calls. Know these without looking them up, and know their costs. For deeper coverage, see Java Collections for DSA.

Java — everyday drill toolkit
import java.util.*; // Hashing — O(1) average Map<Integer, Integer> freq = new HashMap<>(); freq.merge(x, 1, Integer::sum); // count occurrences freq.getOrDefault(x, 0); Set<Integer> seen = new HashSet<>(); if (!seen.add(x)) { /* duplicate */ } // Stack / Queue — use ArrayDeque, not Stack or LinkedList Deque<Integer> stack = new ArrayDeque<>(); stack.push(x); stack.pop(); stack.peek(); Queue<int[]> q = new ArrayDeque<>(); q.offer(new int[]{r, c}); q.poll(); // Heap — O(log n) offer/poll, O(1) peek PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> Integer.compare(a[0], b[0])); // Arrays & strings Arrays.sort(arr); // O(n log n) Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0])); Arrays.fill(dp, Integer.MAX_VALUE); char[] cs = s.toCharArray(); int[] count = new int[26]; count[c - 'a']++; StringBuilder sb = new StringBuilder(); // never concatenate String in a loop // Safe midpoint and overflow int mid = lo + (hi - lo) / 2; long sum = (long) a + b;
⚠️

Integer caching

Compare boxed Integer values with .equals(), not ==. == only works by accident for −128…127.

🧮

Overflow

lo + hi, products, and running sums overflow int. Use long or lo + (hi − lo) / 2.

🔁

Comparators

Use Integer.compare(a, b) instead of a − b. Subtraction overflows for large values of opposite sign.

07
Section Seven · Plan

A 4-Week Study Plan

WeekTopicsDrillsGoal
Week 101 · 02 · 031–32Get O(n) to be your default: hash maps, pointers, windows
Week 204 · 05 · 0633–64Correct loop bounds, pointer rewiring, recursion contracts
Week 307 · 0865–80DFS/BFS from memory, topological sort, Union-Find, Dijkstra
Week 409 · 1081–100Define the state, recurrence and base case before writing any code
How to practise each drill:
  • Read the problem and example only. Close the solution and give yourself 20 minutes.
  • Write the brute force first, even if it's obvious. Then state what it repeats.
  • Compare your answer with the walkthrough diagram, not just the final code.
  • Re-solve from a blank file 3 days later. If you can't, it wasn't learned yet.
  • Track each drill as solved / solved-with-hint / failed, and redo failures at the end of the week.