The Coding Round: Patterns That Keep Coming Back
The six patterns that cover most coding-screen questions, with Java templates, the language-specific traps that cost points, and how to talk while you code without losing your place.
On this page
Coding screens for backend roles reuse a small number of shapes. Recognising which one a problem is matters more than raw algorithmic ability, because recognition is what lets you start writing within two minutes instead of ten.
Key Takeaways
- Six patterns — two pointers, sliding window, hash counting, BFS/DFS, binary search, heap — cover most medium-difficulty questions.
- Say the brute force and its complexity first, then improve it deliberately.
- Java-specific traps cost real points: boxed
==, overflow in a midpoint,chararithmetic. - Talk in checkpoints, not continuously. Narrate the plan, then code, then walk the example.
- Always state the final time and space complexity without being asked.
Pattern 1: two pointers
Sorted array, pair-finding, in-place partitioning, palindromes.
public int[] twoSum(int[] sorted, int target) {
int lo = 0, hi = sorted.length - 1;
while (lo < hi) {
int sum = sorted[lo] + sorted[hi];
if (sum == target) return new int[]{lo, hi};
if (sum < target) lo++; else hi--;
}
return new int[]{-1, -1};
}
// O(n) time, O(1) space — versus O(n^2) brute force or O(n) with a map.The variant with both pointers moving forward — fast and slow — handles cycle detection, removing duplicates in place, and finding the middle of a linked list.
Pattern 2: sliding window
Contiguous subarray or substring with a constraint.
public int longestUnique(String s) {
Map<Character, Integer> lastSeen = new HashMap<>();
int best = 0, start = 0;
for (int end = 0; end < s.length(); end++) {
char c = s.charAt(end);
// Only move the window forward, never backward.
if (lastSeen.containsKey(c) && lastSeen.get(c) >= start) {
start = lastSeen.get(c) + 1;
}
lastSeen.put(c, end);
best = Math.max(best, end - start + 1);
}
return best;
}
// O(n) — each character is visited at most twice.The template is always the same: expand end, and while the window is invalid, shrink start. The
work is in defining "invalid" and in updating whatever state tracks it.
Pattern 3: hash counting
Anything about frequency, grouping, or "have I seen this before".
public List<List<String>> groupAnagrams(String[] words) {
Map<String, List<String>> groups = new HashMap<>();
for (String w : words) {
char[] chars = w.toCharArray();
Arrays.sort(chars);
groups.computeIfAbsent(new String(chars), k -> new ArrayList<>()).add(w);
}
return new ArrayList<>(groups.values());
}counts.merge(key, 1L, Long::sum); // count
index.computeIfAbsent(key, k -> new ArrayList<>()).add(value); // multimap
config.getOrDefault(key, fallback); // safe readUsing merge and computeIfAbsent rather than a get-null-check-put block is a small signal that you
write modern Java, and it removes a whole class of null bug from the code you write under pressure.
Pattern 4: BFS and DFS
Trees, graphs, grids, and anything phrased as "shortest path" or "connected components".
public int shortestPath(Map<String, List<String>> graph, String from, String to) {
Queue<String> queue = new ArrayDeque<>();
Set<String> visited = new HashSet<>();
queue.add(from);
visited.add(from);
int depth = 0;
while (!queue.isEmpty()) {
int levelSize = queue.size(); // process one level at a time
for (int i = 0; i < levelSize; i++) {
String node = queue.poll();
if (node.equals(to)) return depth;
for (String next : graph.getOrDefault(node, List.of())) {
if (visited.add(next)) queue.add(next); // add() returns false if present
}
}
depth++;
}
return -1;
}Two details worth internalising. The levelSize loop is what makes BFS able to report a distance
rather than just a reachability answer. And visited.add(next) returning false for a duplicate lets
you test and insert in one operation.
Deque<String> stack = new ArrayDeque<>();
stack.push(start);
while (!stack.isEmpty()) {
String node = stack.pop();
if (!visited.add(node)) continue;
for (String next : graph.getOrDefault(node, List.of())) stack.push(next);
}Recursion is fine up to roughly ten thousand frames on a default 1MB stack. Saying "I would write this
iteratively for a large input to avoid StackOverflowError" is worth a point even if you then write
the recursive version for clarity.
Pattern 5: binary search
A sorted array, or any monotonic predicate — including "the smallest capacity that finishes in time".
public int firstTrue(int lo, int hi, IntPredicate condition) {
while (lo < hi) {
int mid = lo + (hi - lo) / 2; // NOT (lo + hi) / 2 — that overflows
if (condition.test(mid)) hi = mid; else lo = mid + 1;
}
return lo;
}The overflow is the classic: (lo + hi) / 2 with values near Integer.MAX_VALUE produces a negative
midpoint. This bug lived in the JDK's own Arrays.binarySearch until 2006, which makes it a good
thing to mention by name.
Binary search on the answer — not on an array — is the version that appears most in senior interviews: "what is the smallest number of ships needed to ship all packages in D days?" is a binary search over capacity with a feasibility check.
Pattern 6: heap
Top-k, streaming medians, merging sorted sequences, scheduling.
public List<String> topK(Map<String, Integer> counts, int k) {
// Min-heap of size k: the smallest of the current best sits at the head,
// so it is the one to evict. O(n log k) instead of O(n log n).
PriorityQueue<Map.Entry<String, Integer>> heap =
new PriorityQueue<>(Map.Entry.comparingByValue());
for (var entry : counts.entrySet()) {
heap.offer(entry);
if (heap.size() > k) heap.poll();
}
List<String> out = new ArrayList<>();
while (!heap.isEmpty()) out.add(0, heap.poll().getKey()); // reverse into order
return out;
}Remember that a PriorityQueue is not sorted on iteration — only the head is guaranteed. Printing
one and expecting sorted output is a common slip, covered in
Queues and BlockingQueues.
The Java traps
// 1. Boxed comparison. Works below 128, fails above — the Integer cache.
Integer a = 1000, b = 1000;
a == b; // false. Use a.equals(b) or intValue().
// 2. Overflow in a comparator.
Comparator<Integer> bad = (x, y) -> x - y; // overflows
Comparator<Integer> good = Integer::compare;
// 3. char arithmetic produces an int.
char c = 'a';
c + 1; // int 98, not char 'b'
(char) (c + 1); // 'b'
int index = word.charAt(i) - 'a'; // the standard 0-25 idiom
// 4. Mutating while iterating.
for (String s : list) if (pred(s)) list.remove(s); // CME, or silently skips one
list.removeIf(this::pred); // correct
// 5. Integer division and negative modulo.
5 / 2; // 2
-7 % 3; // -1 in Java, not 2
Math.floorMod(-7, 3); // 2Every one of these is a bug that reaches production, which is exactly why interviewers watch for them.
How to talk while coding
Silence reads as being stuck; continuous narration is exhausting for both of you. Use checkpoints:
Before writing (60–90 seconds). Restate the problem in your own words. Ask about the input size, duplicates, nulls, and whether the input can be modified. State the brute force and its complexity. State the approach you will actually take and why.
While writing. Say what each block does as you start it — "this loop expands the window" — then go quiet and write it. If you get stuck, say what you are stuck on; interviewers hint far more readily than candidates expect.
After writing. Walk one small example through the code out loud. Then check the edge cases you listed: empty input, one element, all identical, the maximum size. Then state the final time and space complexity without being asked.
What to practise
Fifty to eighty problems spread across the six patterns, not several hundred at random. Roughly: fifteen array and two-pointer, ten sliding window, ten hash-map, fifteen tree and graph, ten binary search and sorting, ten heap and interval, and five string manipulation.
For a backend role, that is the right allocation of effort — the rest belongs in system design and in your Spring answers, both of which carry more weight than an extra thirty puzzle problems.
Frequently Asked Questions
How much data-structures practice does a Java backend interview need?
Should I optimise immediately or write the brute force first?
What Java-specific mistakes lose points in a coding round?
Related tutorials
- Spring & Spring Boot Interview QuestionsThe Spring questions asked at every level answered with mechanisms: how auto-configuration decides, why self-invocation breaks @Transactional, proxy modes, bean scopes and testing slices.
- System Design for Java Backend EngineersA 45-minute structure that works: clarify and estimate, data model first, then the API, then scale what the numbers say to scale — plus idempotency, the outbox pattern and talking in numbers.
- The Behavioural Round: STAR Stories for EngineersWhy the behavioural round is scored harder than candidates expect, the six stories that cover almost every question, how to quantify impact honestly, and surviving the follow-up questions.
- The Eight-Week Preparation PlanA week-by-week plan that fits into eight hours a week: what to cover when, how to use spaced repetition on the topics you forget, when to start applying, and how to handle the offer stage.