Coding interview patterns
The cross-cutting techniques that each unlock a whole family of interview problems: two pointers, sliding windows, fast/slow pointers, interval tricks, prefix sums, and monotonic stacks/queues. Interviewers probe these because recognizing the right pattern quickly matters more than memorizing individual solutions.
on this pageshowhide
guide
overview
~1 minProblem patterns are the part of a coding round where preparation shows most clearly. Interviewers rarely care whether you have seen a particular puzzle before; they watch whether you notice the cue in the statement, name the technique it suggests, and can say why that technique is allowed here. The follow-ups are predictable: why the scan is linear when a loop sits inside a loop, which property of the input the technique depends on, and what happens when that property is missing. The third question is the one memorised solutions do not survive. This hub collects the techniques that each unlock a family of problems. [Two pointers](/topics/found-dsa-algo-patterns-two-pointers) and the [sliding window](/topics/found-dsa-algo-patterns-sliding-window) replace a nested loop over pairs or stretches with one forward pass. [Fast and slow pointers](/topics/found-dsa-algo-patterns-fast-slow) find cycles and midpoints without extra memory. [Prefix sums and difference arrays](/topics/found-dsa-algo-patterns-prefix-sums) trade a linear build for constant-time range answers. [Interval techniques](/topics/found-dsa-algo-patterns-intervals) turn scheduling questions into one sort and one scan. [Monotonic stacks and queues](/topics/found-dsa-algo-patterns-monotonic) answer nearest-greater and windowed-extreme questions. Two smaller sections cover [cyclic sort](/topics/found-dsa-algo-patterns-cyclic-sort) over bounded integer ranges and [randomized techniques](/topics/found-dsa-algo-patterns-randomized) such as unbiased shuffling and stream sampling. [Pattern and structure selection](/topics/found-dsa-algo-patterns-selection) works in the other direction, from a fresh statement to the technique and container it needs. Start with two pointers, because most of the other sections are variations on two indices moving forward. The sliding window and prefix sums come next and are best learned together, since each covers the case where the other breaks. Leave selection for last: it only makes sense once you know what you are selecting between. Questions run from junior checks on why a scan is linear to principal-level calls on when saving memory is the wrong choice.
primer
Every technique in this hub is small once you see what it rests on. These ideas recur across all of the sections, and interviewers probe them more than any single recipe. - **A pattern is a structure, an invariant and a licence.** The structure is what you keep (two indices, a window, a stack, a running total); the invariant is the property that stays true after each step; the licence is the precondition on the input that makes the invariant hold. Sortedness licenses converging pointers, non-negative values license a shrinking window for sum targets, a dense range of small integers licenses cyclic sort. Stating all three is what a strong answer sounds like. - **Discarding must be provably safe.** Most of these techniques are fast because they throw candidates away without examining them. The argument an interviewer wants is why nothing thrown away could have been the answer. When the licence is missing, the discard is no longer safe and the technique usually returns a wrong result quietly instead of failing. - **Linear time is usually an amortized argument.** A loop nested inside another loop does not make an algorithm quadratic when every element can enter and leave the structure only a bounded number of times. Counting total moves across the whole scan, not moves per step, is the standard proof, and you should be able to give it without prompting. - **Update incrementally instead of recomputing.** Windows, prefix totals, sweep counters and match tallies all keep a small summary and adjust it as the input slides past. This only works when the summary can be reversed or extended cheaply, and it carries a long-run risk: an accumulated value is never re-checked against the data it summarises. - **Boundaries are where the bugs live.** Half-open versus closed intervals, an array sized one larger than the input, a seeded empty prefix, which event wins a tie, a sentinel that flushes the last pending items. Pick the convention before writing the loop and say it aloud. - **Constant space is often the point, and it has a price.** Fast and slow pointers, cyclic sort and in-place partitioning exist to avoid auxiliary memory, usually by mutating the input or accepting a subtler proof. Knowing when to spend memory instead is a senior-level signal. - **Cues suggest a family, not an answer.** Words like sorted, contiguous, range or next larger narrow the search, but the shape of what is being asked picks the technique within that family.
- Converging pointers
- Two indices starting at opposite ends of a sequence and moving toward each other, each step ruling out every pair through one of the ends.
- Sliding window
- A contiguous range over a sequence, extended at one edge and trimmed at the other, whose summary is updated as it moves rather than rebuilt.
- Frequency map
- A key-to-count table describing which items a window currently holds, needed when the answer depends on identities rather than a single total.
- Floyd's cycle detection
- The tortoise-and-hare method: one pointer advances one step, the other two, and their meeting proves a cycle using constant extra space.
- Functional graph
- A graph in which every node has exactly one outgoing edge, such as repeatedly applying a function; over finitely many nodes every walk ends in a cycle.
- Half-open interval
- A range written [start, end) that includes its start and excludes its end, so adjacent ranges touch without overlapping.
- Sweep line
- A scan over sorted boundary events, each carrying a change to a running count, that replaces reasoning about whole intervals.
- Prefix sum
- The running total of a sequence up to each position; the difference of two prefix totals gives the sum of the stretch between them.
- Difference array
- An array of changes between neighbours, where a range update becomes two point writes and one prefix pass reconstructs the values.
- Monotonic stack
- A stack whose contents stay sorted because each new element first removes the elements it makes irrelevant; it answers nearest greater or smaller queries.
- Monotonic deque
- A double-ended queue kept sorted like a monotonic stack but also expiring items from the front, giving the extreme of a moving window.
- Dominated element
- An item that can never be the answer again because a newer item beats it for every remaining query; monotonic structures evict these.
- Cyclic sort
- In-place placement of each value at the index it names, by repeated swaps, valid when values form a dense bounded integer range.
- Reservoir sampling
- Keeping a fixed-size uniform random sample from a stream whose length is unknown until it ends.
- Fisher–Yates shuffle
- The unbiased in-place shuffle that swaps each position only with positions not yet fixed, producing every ordering with equal probability.
The sections look like a list of unrelated tricks, but most of them are variations on a few moves, and knowing the family tree makes the questions easier to place. **Two pointers is the root.** Converging pointers exploit order to rule out pairs from both ends. Same-direction pointers are the in-place filtering and merging form. The [sliding window](/topics/found-dsa-algo-patterns-sliding-window) is same-direction pointers with a summary of what lies between them and a condition that says when to trim. [Fast and slow pointers](/topics/found-dsa-algo-patterns-fast-slow) keep two indices on one path but move them at different speeds, which turns a linked chain or any repeated function into something you can measure without storing it. **Windows and prefix sums cover each other's gaps.** A shrinking window needs the summary to move in one direction as the window grows, which for sums in practice means non-negative values. [Prefix sums](/topics/found-dsa-algo-patterns-prefix-sums) paired with a map of totals already seen need no such property, at the cost of memory. A difference array is the same idea run backwards, and a sweep line is a difference array laid over coordinates instead of indices, which is why [interval problems](/topics/found-dsa-algo-patterns-intervals) so often reduce to sorting boundaries and keeping a running count. **Monotonic structures combine a stack with an eviction rule.** A [monotonic stack](/topics/found-dsa-algo-patterns-monotonic) resolves each element when something beats it; a monotonic deque adds expiry from the front, which makes it a sliding window that also tracks the extreme. Both share the amortized argument two pointers use: every element is handled a bounded number of times. **In-place and randomized techniques sit alongside.** Partition-style pointers, [cyclic sort](/topics/found-dsa-algo-patterns-cyclic-sort) and the split-and-reverse linked-chain routines all rearrange the input to save space, so they share the question of whether mutating it is allowed. [Randomized techniques](/topics/found-dsa-algo-patterns-randomized) connect back to partitioning through the random pivot and stand apart through shuffling and sampling. **Selection ties it together.** The [selection](/topics/found-dsa-algo-patterns-selection) section starts from the statement instead of the technique: which cue is present, which licence the input grants, which operation must be cheap, and so which pattern and container follow. It draws on the structure choices from the parent [data structures and algorithms](/topics/found-dsa) hub as much as on the patterns here.
- Two Pointers →
The simplest pattern and the root of several others; it teaches how an input property makes discarding candidates safe.
- Sliding Window →
Two pointers plus a running summary; the most common contiguous-stretch technique and the first place amortized reasoning is tested.
- Prefix Sums & Difference Arrays →
Learn right after windows: it handles the negative-value cases a window cannot, and introduces difference arrays for range updates.
- Interval Techniques →
Sorting plus one invariant; the sweep line builds directly on the difference-array idea from the previous step.
- Monotonic Stacks & Queues →
Needs the stack and amortized reasoning already in hand; eviction of dominated elements is the invariant interviewers probe hardest.
- Pattern & Structure Selection →
Last, because mapping a fresh statement to a pattern requires knowing the patterns and their preconditions first.
Running converging pointers on unsorted input, or a shrinking window over values that can be negative; the code still returns something, often not the answer.
Calling a scan quadratic because it has a loop inside a loop, or claiming linear time without the argument that each element is processed a bounded number of times.
Mixing closed and half-open interval conventions in one solution, so touching ranges are merged in one place and kept apart in another.
Forgetting the seeded zero total in a prefix-sum map, which silently drops every qualifying stretch that starts at the first element.
Recording the best window after trimming instead of while the window is still valid, so the reported length belongs to an invalid window.
Leaving a caller's linked chain reversed after an in-place check, or mutating input the problem never said you could change.
Storing values instead of positions in a monotonic deque, which leaves no reliable way to tell when an item has left the window.
Naming a pattern from a single keyword and starting to code before checking that the input actually satisfies its precondition.
Many questions in this hub end with a choice between two workable versions, and the interviewer wants to hear what decides it. - **Constant space versus a simple proof.** Fast and slow pointers, cyclic sort and in-place reversal save memory but depend on a less obvious argument and often on mutating the input. A visited set or a copied array uses linear space and is easy to verify, and it is the better call when memory is not the constraint or the code will be maintained by many people. - **Window versus prefix map.** A window uses constant extra space but needs a monotone summary. A prefix map works for any values and costs a map proportional to the input. The value range decides. - **Preprocessing versus per-query work.** A prefix or difference array pays once so that many range queries or updates become constant time; for a single query it is wasted effort. - **Incremental state versus recomputation.** Rolling summaries are fast, but they accumulate rounding and bookkeeping errors over long runs, while recomputing from the data corrects itself. Long-lived systems sometimes do both, rebuilding periodically. - **Heap versus ordered structure.** A heap is enough when only the extreme is read; once ordered views or range queries become frequent, a balanced tree earns its extra cost. - **Expected versus worst-case guarantees.** A random pivot does not improve the worst case, it removes any fixed input that triggers it. Whether that is acceptable depends on who controls the input and whether an occasional slow run or an occasional wrong answer is the tolerable failure.
Beyond the invariants and boundary habits above, a few problem shapes recur across sections under different names. Recognising them makes an unfamiliar variant feel familiar. - **Sort first, then scan once.** Pair and triple sums, interval merging, room counting and sweep lines all buy a linear pass with an upfront sort. When a problem looks quadratic over unordered data, ask what sorting would make monotone. - **Recode, then match totals.** Turning a condition into signed values (+1 and -1, or deltas at boundaries) converts balance, zero-sum and concurrency questions into a search for equal or extreme running totals. - **Keep positions, look up values.** A stored position gives you the value by lookup and also the item's age or extent, which a bare value cannot. - **Add a guard element.** A sentinel bar, an extra array slot or a seeded empty prefix removes a special case at one end of the input. - **Undo what you changed.** Any in-place technique that rearranges shared input needs a restore on every exit path, early returns included. For the reverse direction, from statement to pattern, see [pattern and structure selection](/topics/found-dsa-algo-patterns-selection).
explore
- Two Pointers12 questions
- Converging Pointers4 questions
- Same-Direction Pointers4 questions
- Partition-Style Pointers4 questions
- Sliding Window11 questions
- Fixed-Size Windows4 questions
- Variable-Size Windows4 questions
- Window-State Bookkeeping3 questions
- Fast & Slow Pointers8 questions
- Cycle Detection in Implicit Sequences4 questions
- Splitting for Palindrome & Reorder4 questions
- Interval Techniques12 questions
- Merging & Inserting Intervals4 questions
- Overlap Detection & Scheduling4 questions
- Sweep Line4 questions
- Prefix Sums & Difference Arrays13 questions
- Prefix Arrays & Range Queries4 questions
- Subarray Sums with Hash Maps5 questions
- Difference Arrays4 questions
- Monotonic Stacks & Queues12 questions
- Next Greater Element4 questions
- Histogram & Span Reasoning4 questions
- Monotonic Deque & Window Maximum4 questions
- Pattern & Structure Selection9 questions
- Problem Cues to Patterns4 questions
- Choosing the Data Structure5 questions
- Cyclic Sort4 questions
- Randomized Techniques4 questions
- Data Structures & Algorithmsskillanchors this topic
- AI & Data Scientistrole
- AI Engineerrole
- AI Red Teamingrole
- Android Developerrole
- Backend Developerrole
- Blockchain Developerrole
- Cyber Security Expertrole
- Data Analystrole
- Data Engineerrole
- DevOps / SRE Engineerrole
- DevSecOps Engineerrole
- Forward Deployed Engineerrole
- Frontend Developerrole
- Full Stack Developerrole
- Game Developerrole
- Java Backend Developerrole
- Java SDETrole
- Kotlin Backend Developerrole
- MLOps Engineerrole
- Machine Learning Engineerrole
- Network Engineerrole
- PostgreSQL DBArole
- QA Engineerrole
- Software Architectrole
- iOS Developerrole
questions
85 · 9 sectionsWhy does the converging two-pointer technique for finding a pair with a target sum require sorted input?
basics
~20 sSorted order gives each comparison a direction: a sum below the target is only fixable by advancing the low end, one above only by retreating the high end. With unsorted input no move is provably safe, so the scan could skip the answer.
In a same-direction two-pointer sweep over one array, why is the cost O(n) and not O(n^2)?
basics
~20 sBoth cursors only move forward and neither restarts, so each takes at most n steps in total — roughly 2n operations. Nested loops cost O(n^2) because the inner one restarts from scratch; two monotone cursors inside one loop never do.
After one partition pass around a pivot value, what is guaranteed about the array?
basics
~20 sA partition pass guarantees only a two-region split: everything left of the boundary is at most the pivot value, everything right is at least it. Neither region is sorted, and the two sides need not be the same size.
What loop invariant makes the converging-pointer pair-sum search on a sorted array exact — why can an inward move never skip the answer?
basics
~20 sThe invariant: if any qualifying pair exists, at least one still lies inside the window between the pointers. Each move discards only pairs proven impossible — a too-small sum condemns every pair through the low element — so no answer is ever skipped.
In an in-place sweep collapsing consecutive equal timestamps in a sorted log, what does the slow index mark?
basics
~20 sSlow marks the last slot already written — the end of the kept prefix, not the next free one. Positions 0 through slow hold distinct timestamps, so the surviving length is slow + 1, and an empty log needs its own guard.
Why is a rolling sum over every length-k window O(n) work while recomputing each window costs O(n·k)?
basics
~20 sAdjacent windows differ by exactly two elements, so a rolling sum adds the entering value and subtracts the leaving one in constant time instead of re-adding all k. Across n slides that is O(n) total work rather than O(n·k).
When does a sliding window need a frequency map instead of just a running sum?
basics
~20 sA running sum suffices when the answer is a single reversible total, like hours worked. A per-key frequency map is needed when the answer depends on which distinct keys are present, not just on a total.
In a variable-size sliding window, what decides when the right edge grows versus when the left edge shrinks?
basics
~10 sThe right edge grows every iteration to admit the next element; the left edge shrinks only when the window's constraint is violated, advancing until the window is valid again. Growth explores; shrinking repairs.
Why is a grow-right/shrink-left sliding window O(n) overall when a shrink while-loop sits inside the main loop?
basics
~20 sBecause both pointers only move forward. The right pointer takes at most n steps and the left pointer at most n steps across the entire scan, so total work is bounded by about 2n pointer moves — O(n).
How does a single mismatch counter make a fixed-window frequency check O(1) per slide?
basics
~20 sOnly two symbols change per slide, so rather than comparing whole count tables you keep a tally of how many symbols disagree with the target counts and adjust it for those two. The window matches when the tally is zero.
Why can't a singly linked chain be palindrome-checked by converging pointers from both ends?
basics
~20 sA singly linked chain has no backward pointers, so nothing can walk from the tail inward. The standard fix splits the chain at the middle, reverses the back half in place, then compares the two halves node by node.
What must the step function f guarantee for tortoise-and-hare detection on x = f(x) to be correct?
basics
~20 sThe step must be deterministic and side-effect-free, must give every reachable state exactly one successor over a finite set, and must be cheap to re-evaluate. Branching states, or a walk that can simply end, invalidate the two-pointer loop.
When is a visited-set loop check the right call over constant-space fast/slow pointers?
basics
~20 sUse a visited set when the state count is small, when the step is expensive enough to want each transition computed once, or when the report must name the looping states. Use two pointers when memory is the binding constraint.
Why does iterating x = f(x) over a finite value range always repeat a value?
basics
~20 sWith finitely many values, among the first N+1 terms two must be equal — pigeonhole. Because the step depends only on the current value, that repeat locks the sequence into a loop forever: tail, then cycle.
Why does following i to a[i] in an array whose values are all valid indices guarantee a loop?
basics
~20 sEvery slot holds exactly one valid index, so each position has exactly one successor over finitely many positions. That deterministic walk can never end and can never avoid revisiting a position, so it must fall into a loop.
Why must overlapping intervals be sorted by start before a single-pass merge?
basics
~20 sSorting by start guarantees any interval that could overlap the one being built arrives before the pass moves past it. In arrival order, an overlapping slot can appear after you already emitted an interval, so a single pass misses merges.
What single condition tells you two half-open intervals [start, end) overlap?
basics
~20 sTwo half-open intervals overlap exactly when a.start < b.end and b.start < a.end. That pair of strict comparisons is the negation of the only two ways intervals can miss each other: one finishing at or before the other begins.
How does a sweep line find the maximum number of sessions open at once in a login/logout log?
basics
~20 sA sweep line throws away the intervals and keeps only their boundaries: +1 at each login coordinate, -1 at each logout. Sort those events by coordinate, scan once with a running sum, and remember the largest sum seen.
When merging sorted intervals, why extend with max(end, next.end) instead of next.end?
basics
~20 sSorting by start does not order the ends, so the next interval can be fully contained in the open one. Assigning next.end there truncates coverage that the input actually had; max keeps the furthest end seen and handles containment with no special case.
How does a min-heap of end times find the minimum number of servers a set of scheduled campaign flights needs?
basics
~20 sSort the flights by start time, then walk them keeping every currently-running end time in a min-heap. Before each flight, pop all end times at or before its start; push its own end. The largest heap size seen is the answer.
Why do two O(1) writes to a difference array record an increment across a whole index range?
basics
~20 sA difference array stores the gap between neighbouring entries. Adding v at index l and subtracting v at index r+1 raises the running total by v for exactly positions l through r, and one prefix pass turns those two marks back into real values.
How does a running total plus a map of seen totals count zero-net stretches in a signed ledger?
basics
~20 sKeep a running total of the signed deltas and a map counting how often each running total has already appeared. Two positions with the same running total bracket a stretch that nets to zero, so each earlier match adds one more qualifying stretch.
Why does a prefix-sum array answer range sums in O(1), and why is it sized n+1?
basics
~20 sA prefix array stores running cumulative totals, so any range sum becomes one subtraction: the total over positions l..r equals P[r+1] - P[l]. The extra leading slot holds 0, so ranges that begin at index 0 need no special case.
In prefix-sum counting with a hash map, why must the empty prefix (total 0) be seeded first?
basics
~20 sWithout a seeded entry for total 0, every qualifying stretch that begins at the first element is lost. Those stretches need the running total from before any element was read, and the only way the map can offer it is to record total 0 once up front.
Why is a difference array called the inverse of a prefix sum, and when does that duality pay off?
basics
~20 sTaking running sums and taking successive differences undo each other, so either transform recovers the original array. That duality splits the work: prefix arrays make reads cheap and writes useless, difference arrays make range writes cheap and defer all reading to one pass.
In a rolling-maximum deque over the last k readings, why can an older smaller reading be dropped forever?
basics
~20 sA reading older and smaller than the newest one can never win again: every remaining window that contains it also contains that newer, larger reading. Being dominated, it is evicted from the back and never revisited.
In a next-greater-element scan over an array, what do the indices on the stack represent?
basics
~10 sThe stack holds indices of items still waiting for a greater value to their right, kept in decreasing order of value. Each new item answers every stacked index it beats, then is pushed itself.
A rolling-maximum deque has a nested eviction loop, so why is the whole scan O(n)?
basics
~20 sEach position is appended to the candidate list exactly once and removed at most once, so the inner eviction loop performs at most n removals across the entire scan. Total work is linear even though a single step can evict many candidates.
Scanning building heights with a monotonic stack, why is the widest rectangle capped by a bar computed only when that bar is popped?
basics
~20 sA rectangle needs both edges. The right edge stays unknown until a shorter bar arrives, and that arrival is exactly what triggers the pop; the left edge is the bar left underneath on the stack. Only at pop time are both known.
Why is a monotonic-stack next-greater scan O(n) when a while loop sits inside the for loop?
basics
~20 sEvery index is pushed exactly once and popped at most once, so the inner while loop runs at most n times in total across the scan. Total work is linear even though one step may pop many indices.
How do you choose between a set, a counter map, and a key-to-index map?
basics
~20 sChoose by what you must read back later. A set answers only "have I seen this?". A counter map answers "how many times?". A key-to-index map answers "where did it first appear?". Store the least that answers your question.
What pattern does each cue suggest: sorted input, longest contiguous stretch, and next-stronger-later value?
basics
~20 sA cue narrows the pattern family: sorted input points to converging pointers or binary search, a longest contiguous stretch points to a sliding window or prefix sums, and 'next stronger later value' points to a monotonic stack.
Why is a hash map keyed by timestamp wrong for "latest slot at or before a given time"?
basics
~20 sHashing scatters keys, so a hash map holds no ordering. It answers exact-key lookups in expected O(1) but cannot find the nearest smaller key without inspecting every entry — an O(n) scan. Predecessor and range queries need an order-preserving structure.
Union-find or repeated graph traversal for connectivity queries as edges keep arriving?
basics
~20 sThe interleaving decides, not the graph. If edges arrive between queries, union-find answers each merge and check in amortized near-constant time. If the edge set is known up front, one traversal labels every component and each check is a label comparison.
Why does the shrinking sliding window break when a contiguous-stretch problem allows negative values?
basics
~20 sThe shrinking window assumes the total only rises when you extend right and only falls when you advance the left edge. Negative values break that monotonicity, so a discarded left endpoint can still belong to the answer.
In cyclic sort over values 1..n, why does one final scan reveal a missing value?
basics
~20 sCyclic sort moves every value v to index v-1, so once placement finishes index i must hold i+1. The first index that breaks that rule names the absent value outright, with no extra lookup structure.
Cyclic sort can swap repeatedly without advancing its index — why is the total work still O(n)?
basics
~20 sEvery swap parks one value permanently on its home index, and a settled index is never disturbed again. So total swaps are capped by the slot count, and the cursor advances at most that many times — linear overall.
In cyclic sort over values 1..n, why must the swap guard compare values rather than indices?
basics
~20 sAn index-based guard spins forever on duplicates: two slots holding the same value swap identical contents while the cursor never advances. Comparing the current value against what already sits at its home fires the skip branch and guarantees progress.
When would you reject cyclic sort for a missing-token audit and reach for something else?
basics
~20 sReject it when the values are not a dense bounded range, or when the buffer is read-only, shared, or must keep its arrival order. Recognising the missing license is the actual skill the question tests.
In a shuffle, why is swapping each element with a uniformly random index biased?
basics
~10 sThe naive loop has n^n equally likely execution paths but only n! orderings, and n! does not divide n^n. Some orderings therefore come out more often than others, however good the random source is.
In reservoir sampling over a stream of unknown length, why keep item i with probability k/i?
basics
~20 sKeeping the i-th item with probability k/i, and evicting a uniformly chosen resident, holds the invariant that after i items each is held with probability k/i. That holds at every prefix, so the length is never needed.
Why does choosing a partition pivot at random help when the worst case is still O(n^2)?
basics
~20 sRandomizing moves the bad case from the input to the coin. The worst-case bound is unchanged, but no fixed input triggers it reliably any more: expected cost becomes good for every input, not only for inputs assumed to be unordered.
In a billing pipeline, when is a Monte Carlo algorithm's error probability unacceptable but a Las Vegas one's variable runtime fine?
basics
~20 sA Las Vegas algorithm is always correct with variable runtime; a Monte Carlo one has bounded cost and a chance of being wrong. Figures that must reconcile exactly can absorb a late finish, never a wrong number.