Coding Interview Patterns You Must Know
Grinding 500 random LeetCode problems is the slow way. Almost every coding interview question is one of a few recurring patterns — learn to recognise them and the problems start solving themselves.
Here's the thing nobody tells you when you start preparing for coding interviews: you are not expected to invent clever algorithms on the spot. The interviewer is checking whether you can recognise a familiar shape and apply a known technique to it.
That's great news, because there are only a handful of shapes. Learn these 8 coding interview patterns, learn the signal that points to each one, and you'll walk into the room pattern-matching instead of panicking. Let's go.
How to pick a pattern fast
Before the patterns themselves, internalise this: the problem statement almost always tells you which tool to grab. Train yourself to spot the signal.
Keep that map in your head. Now here's each pattern, when to reach for it, and a quick taste of how it works.
1. Two Pointers
The signal: a sorted array (or string) where you're looking for a pair, a triplet, or you need to compare from both ends.
Instead of a nested loop (O(n²)), you walk two pointers inward from each end, moving them based on the comparison. It collapses the work to O(n).
// Find two numbers in a sorted array that sum to target.
function twoSum(nums, target) {
let left = 0, right = nums.length - 1;
while (left < right) {
const sum = nums[left] + nums[right];
if (sum === target) return [left, right];
if (sum < target) left++; // need a bigger sum
else right--; // need a smaller sum
}
return [];
}
2. Sliding Window
The signal: "longest / shortest / maximum" over a contiguous subarray or substring.
You keep a window that grows and shrinks across the array, updating an answer as you go — so each element is visited once instead of re-scanning ranges.
// Longest substring without repeating characters.
function longestUnique(s) {
const seen = new Set();
let left = 0, best = 0;
for (let right = 0; right < s.length; right++) {
while (seen.has(s[right])) seen.delete(s[left++]); // shrink
seen.add(s[right]); // grow
best = Math.max(best, right - left + 1);
}
return best;
}
3. Fast & Slow Pointers
The signal: a linked list (or a sequence) where you need to detect a cycle, find the middle, or spot a repeat.
Two pointers move at different speeds. If there's a loop, the fast one eventually laps the slow one and they meet — the classic "tortoise and hare".
// Detect a cycle in a linked list.
function hasCycle(head) {
let slow = head, fast = head;
while (fast && fast.next) {
slow = slow.next; // 1 step
fast = fast.next.next; // 2 steps
if (slow === fast) return true;
}
return false;
}
4. Binary Search
The signal: the input is sorted, or you're searching a range of answers for the smallest/largest value that works.
Halve the search space every step — O(log n). The trick interviewers love: binary search isn't just for arrays, it's for any monotonic answer space ("what is the minimum capacity that ships everything in D days?").
function binarySearch(nums, target) {
let lo = 0, hi = nums.length - 1;
while (lo <= hi) {
const mid = lo + ((hi - lo) >> 1); // avoids overflow
if (nums[mid] === target) return mid;
if (nums[mid] < target) lo = mid + 1;
else hi = mid - 1;
}
return -1;
}
5. BFS & DFS (tree and graph traversal)
The signal: anything shaped like a tree or graph — levels, shortest path, connected components, "can you reach X from Y".
- BFS (breadth-first) explores level by level using a queue — perfect for shortest paths in unweighted graphs.
- DFS (depth-first) dives down one branch using recursion or a stack — great for exploring all paths or detecting cycles.
// BFS over a tree, level by level.
function bfs(root) {
const queue = [root], order = [];
while (queue.length) {
const node = queue.shift();
order.push(node.val);
for (const child of node.children) queue.push(child);
}
return order;
}
6. Backtracking
The signal: "generate all combinations / permutations / subsets", or a puzzle like Sudoku or N-Queens.
You build a candidate step by step, and the moment it can't lead to a valid solution you undo the last choice and try another. It's brute force with a brain.
// All subsets of a set.
function subsets(nums) {
const result = [];
function backtrack(start, path) {
result.push([...path]);
for (let i = start; i < nums.length; i++) {
path.push(nums[i]); // choose
backtrack(i + 1, path); // explore
path.pop(); // un-choose (backtrack)
}
}
backtrack(0, []);
return result;
}
7. Dynamic Programming
The signal: "how many ways…", "minimum/maximum cost…", and the problem breaks into overlapping subproblems whose answers you'd otherwise recompute.
The whole idea is to remember sub-answers instead of recomputing them — either top-down (memoised recursion) or bottom-up (filling a table). DP scares people, but every DP problem is just: define the subproblem, then combine sub-answers.
// Classic: Fibonacci, but the pattern generalises to most DP.
function fib(n) {
const dp = [0, 1];
for (let i = 2; i <= n; i++) dp[i] = dp[i - 1] + dp[i - 2];
return dp[n];
}
Interview tip: when you smell DP, say it out loud and write the recurrence first ("the answer at i depends on i-1 and i-2"). The code follows easily once the recurrence is right.
8. Top-K Elements (Heaps)
The signal: "the K largest / smallest / most frequent" something.
A heap (priority queue) keeps the best K items as you stream through the data — O(n log k) instead of sorting everything at O(n log n). Reach for it whenever you see the words "top K", "K closest", or "K most frequent".
// Keep a min-heap of size k → its root is the kth largest.
// (Using a library/heap structure in a real interview.)
function kthLargest(nums, k) {
const minHeap = new MinHeap();
for (const n of nums) {
minHeap.push(n);
if (minHeap.size() > k) minHeap.pop(); // drop the smallest
}
return minHeap.peek();
}
The cheat sheet
Tape this to your monitor. When you read a problem, find the signal, grab the pattern:
| If the problem says… | Reach for |
|---|---|
| Sorted array, find a pair | Two Pointers |
| Longest/shortest contiguous substring | Sliding Window |
| Linked list cycle or middle | Fast & Slow Pointers |
| Sorted input, or "minimum X that works" | Binary Search |
| Tree/graph, shortest path or levels | BFS |
| Tree/graph, all paths or cycle check | DFS |
| All combinations / permutations | Backtracking |
| Count ways, min/max cost, overlapping subproblems | Dynamic Programming |
| Top / K most frequent / K closest | Heap |
How to actually practise this
Patterns only stick when you label problems as you solve them. Don't just get the green check — say which pattern it was and what signal gave it away. After 5–10 problems per pattern, you'll start reading a question and immediately knowing which tool to grab. That recognition speed is the whole game.
And remember: in the real interview, talk through the pattern before you code. Naming "this looks like a sliding-window problem because…" shows the interviewer exactly the structured thinking they're hiring for.