The core LeetCode patterns (and how to actually recognize them)
By Jerry, founder of Nudge · 15-pattern reference guide · Updated August 13, 2026
Most "LeetCode patterns" lists are the same twenty problems reshuffled under different headings. That's not useless, but it teaches you to recognize twenty problems, not to recognize a pattern in the 2,001st problem you've never seen, which is the actual skill interviews test.
This is the standard taxonomy that shows up across NeetCode 150, Blind 75, and most FAANG-style loops: fifteen patterns, each with what it is, the specific signal that should make it click when you read a new problem, and a couple of problems you'd recognize it from. No solutions, no filler, just the recognition heuristics.
1. Two Pointers
Two indices walk through a sorted array or list (typically from opposite ends closing inward, or one trailing the other), collapsing what looks like an O(n²) pair search into a single O(n) pass.
Recognize it: you need to find a pair, triplet, or partition in an array that's sorted (or cheap to sort), and moving one side of the candidate window in one direction predictably increases or decreases the quantity you're checking. If a sorted array and a target sum/condition appear together, you almost never need nested loops. You need two pointers moving toward each other.
Example problems: Two Sum II, 3Sum.
2. Sliding Window
A contiguous window [left, right] over an array or string expands and contracts instead of being recomputed from scratch for every start position.
Recognize it: the question asks for a contiguous subarray or substring (longest, shortest, or count) satisfying some property, and the property is monotonic under expansion: extending the window right can only make the constraint harder to satisfy, so shrinking from the left is always the correct fix, never a reason to restart. That monotonicity is what lets you slide instead of re-scan, turning an O(n²)/O(n·26) brute force into O(n).
Example problems: Longest Substring Without Repeating Characters, Minimum Window Substring.
3. Fast & Slow Pointers (cycle detection)
Two pointers traverse the same chain of "next" links at different speeds, usually one step versus two. If the chain loops back on itself, the fast pointer eventually laps the slow one and they meet (Floyd's algorithm).
Recognize it: you're dealing with a linked list, or any sequence generated by repeatedly applying a function to get the "next" value (not just an explicit list), and the question is about a cycle, finding a midpoint, or detecting a repeat, all without using O(n) extra space for a visited set. Anywhere you'd reach for a hash set to track "have I seen this node before," fast/slow pointers get the same answer in O(1) space.
Example problems: Linked List Cycle, Find the Duplicate Number.
4. Binary Search (including binary search on the answer)
Repeatedly halving a search space based on a monotonic predicate, giving O(log n) instead of O(n). The classic form searches a sorted array; the less obvious form, binary search on the answer, searches the space of possible answers, not the input.
Recognize it: for the classic form, "sorted array" is the tell. For binary search on the answer, the tell is different and easy to miss: the problem asks for the minimum or maximum value of some quantity such that a condition holds (e.g. "minimum capacity so all packages ship in D days"), and you can write a fast feasibility check ("is answer X good enough?") whose result flips exactly once as X increases. Any time the feasibility function is monotonic (false, false, …, true, true), you can binary search over the answer range and call the checker at each midpoint, even though nothing in the input is sorted.
Example problems: Search in Rotated Sorted Array, Koko Eating Bananas.
5. BFS
Queue-driven traversal that explores every node at distance k from the start before touching any node at distance k+1, level by level.
Recognize it: "shortest path" or "minimum number of steps/moves" in a graph or grid where every edge has the same cost (unweighted). BFS is the one traversal that guarantees the first time you reach a node is via a shortest path. DFS explores depth-first and can find *a* path long before it finds the shortest one. Also the default for tree level-order output, since the queue naturally processes one level at a time.
Example problems: Binary Tree Level Order Traversal, Word Ladder.
6. DFS / Backtracking
DFS follows one branch as deep as it goes before retreating. Backtracking is DFS plus an explicit undo: you make a choice, recurse, and if it doesn't pan out you revert the choice and try the next one, building a decision tree of partial solutions and pruning branches that can't work.
Recognize it: "find all," "generate all," or "does a valid arrangement exist": subsets, permutations, combinations, valid board configurations. If the answer is a set of *configurations* rather than a single number, and you'd naturally describe the solution as "try each choice, and if it fails, take it back," that's backtracking. Plain DFS (no undo needed) covers connectivity questions: does a path exist, what's in this component, can you reach node B from A.
Example problems: Permutations, Word Search.
7. Dynamic Programming: 1D
A recurrence where dp[i] (the answer considering the first i elements, or ending at index i) is computed from a small number of earlier states like dp[i-1] and dp[i-2], cached (memoization) or built bottom-up (tabulation) so each state is computed once.
Recognize it: "number of ways to…" or "max/min … up to index i," where a brute-force recursive solution would call itself with the same argument many times. That repeated overlap in the recursion tree is the actual DP signal, distinct from backtracking, where the recursive calls don't revisit the same state. If you can draw the recursion and see the same sub-problem appear more than once, cache it.
Example problems: Climbing Stairs, House Robber.
8. Dynamic Programming: 2D / grid
Same idea as 1D DP, but the state needs two indices: dp[i][j], usually meaning "position i in one sequence versus position j in another" or "the cell at row i, column j."
Recognize it: two flavors. (1) You're comparing two strings or sequences element by element (matching, editing, or aligning them), so dp[i][j] represents "using the first i characters of A and the first j characters of B." (2) You're moving through a grid with constrained moves (right/down), accumulating a count or cost, so dp[i][j] is built from dp[i-1][j] and dp[i][j-1]. Two sequences or a grid, plus an optimization/counting question, is the tell.
Example problems: Longest Common Subsequence, Unique Paths.
9. Greedy
Make the locally best choice at each step and never reconsider it, relying on a proof (usually an exchange argument) that no other choice at that step could lead to a better global outcome.
Recognize it: this is the hardest pattern to spot on sight because it looks like DP or two pointers from the outside. The tell is that sorting by some key (deadline, start time, ratio of value to cost) makes the correct choice at each step obvious and irrevocable, with no need to compare against alternate paths later. If you can't convince yourself a locally optimal choice is safe (or you can find a counterexample), it's not greedy; fall back to DP.
Example problems: Jump Game, Gas Station.
10. Merge Intervals
Sort a list of (start, end) ranges by start time, then sweep through once, merging or comparing each interval against the last one you kept.
Recognize it: the input is a list of ranges and the question involves overlap: merging overlapping ranges, inserting a new range, or counting how many overlap at once. Sorting by start (occasionally by end) is what turns an all-pairs comparison into a single linear sweep, since after sorting you only ever need to compare each interval to the most recently merged one.
Example problems: Merge Intervals, Insert Interval.
11. Heap / Top-K Elements
A min-heap or max-heap keeps partial order over a collection so the smallest or largest element is always available in O(1), with O(log n) insert and extract.
Recognize it: the phrase "kth largest," "k most/least frequent," or anything requiring repeated access to a running min or max as data streams in. The efficiency argument is specific: if you only need the top k out of n elements, a heap of size k gives you O(n log k) instead of sorting everything for O(n log n), worth reaching for whenever k is meaningfully smaller than n. Also the standard tool for merging several already-sorted sequences, since a heap of the current head of each list gives you the next overall element in O(log(number of lists)).
Example problems: Top K Frequent Elements, Merge k Sorted Lists.
12. Union-Find (Disjoint Set)
A structure that tracks a partition of elements into disjoint groups, supporting find (which group is this in) and union (merge two groups). With path compression and union by rank, both operations are amortized nearly O(1), technically O(α(n)), the inverse Ackermann function.
Recognize it: connectivity that's revealed incrementally: you're adding edges one at a time and repeatedly need to answer "are these two nodes already connected" or "how many separate groups exist right now." That incremental, query-as-you-go shape is what distinguishes it from BFS/DFS, which assume the whole graph is already built before you traverse it. Cycle detection while building an undirected graph edge-by-edge is the single most recognizable trigger: if the two endpoints of a new edge already belong to the same set, that edge creates a cycle.
Example problems: Number of Connected Components in an Undirected Graph, Redundant Connection.
13. Trie
A prefix tree: each node is a character, and the path from the root to any node spells out a prefix shared by every word that passes through it.
Recognize it: you're doing repeated prefix matching against a fixed dictionary of strings: autocomplete, "does any word start with this," or a grid word search checked against a word list. The distinction from a plain hash set is the operation you need: a hash set answers "is this exact string present," a trie answers "is anything starting with this string present," and it lets you abandon a search the moment no word in the dictionary shares your current prefix.
Example problems: Implement Trie (Prefix Tree), Word Search II.
14. Monotonic Stack
A stack maintained in strictly increasing or decreasing order: before pushing a new element, you pop off everything it invalidates. Each element is pushed and popped at most once, so the total work across the whole array is O(n) even though it doesn't look like it at first glance.
Recognize it: "next greater element," "next smaller element," or anything asking, for every position, how far you'd have to look left or right to find a bigger (or smaller) value. The naive version of that question is O(n²): check every pair. A monotonic stack answers it in one left-to-right pass by keeping only the "unresolved" candidates on the stack and popping them the instant the current element resolves them.
Example problems: Daily Temperatures, Largest Rectangle in Histogram.
15. Prefix Sum
Precompute a running-total array where prefix[i] is the sum of everything before index i. Once built, the sum of any range [i, j] is prefix[j+1] - prefix[i] in O(1), after an O(n) one-time cost.
Recognize it: repeated range-sum queries over an array that isn't changing. The moment you see "sum of subarray" asked more than once, stop recomputing sums on the fly and precompute prefixes first. The less obvious variant: "number of subarrays with sum equal to k" is also a prefix-sum problem: you walk the array tracking a running prefix sum and a hash map of how many times each prefix sum has occurred, and check for currentSum - k at every step instead of testing every subarray directly.
Example problems: Subarray Sum Equals K, Range Sum Query - Immutable.
Recognizing the category is maybe the first fifth of solving a new problem. Turning that recognition into a correct, efficient implementation under time pressure is the rest, and that only comes from doing problems, not reading about them. If you're mid-problem and stuck on that second part, that's what Nudge is for: it notices when you're stuck and gives the next hint, not the full solution.