skip to content

questions

12

Why does the converging two-pointer technique for finding a pair with a target sum require sorted input?

level: juniorimportance: must knowfreq 78%

answer

  1. what does one comparison prove?
  2. the high end is the largest remaining
  3. too small — only one move can help
  4. each step safely retires one element
  5. unsorted ends prove nothing about partners

basics

~20 s

Sorted 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.

solid answer

~50 s

Place one pointer at each end and compare `a[lo] + a[hi]` to the target. On a match you are done; if the sum is too small, the only way to raise it is `lo = lo + 1`, because `a[hi]` is already the largest value still in play; if too big, only `hi = hi - 1` can lower it. That decision rule is exactly what sortedness buys: each comparison proves one end's element can never be part of an answer inside the window, so discarding it is safe. On unsorted data the comparison tells you nothing about where a better partner sits, and an inward move could walk past the answer — so sorting is a correctness precondition, not a speed-up. The scan does at most n-1 moves: O(n), plus O(n log n) first if you must sort.

go deeper

for a junior

Be ready to state the setup — one pointer per end of sorted data — the three-way decision on the sum, and the O(n) cost of the pass. Say clearly that sortedness is what makes each move safe.

for a middle

An interviewer expects the direction argument: a too-small sum means the low element can pair with nothing remaining, because the high end is the largest candidate left. Explain it, don't just assert it.

for a senior

Be ready to place the pattern among alternatives: sorting cost versus auxiliary-space cost, when the input is already sorted, and how the argument generalizes to any pairwise predicate that is monotone in each element.

for a principal

Own the framing: this pattern is a worked example of exploiting input structure to delete a loop. Use it to probe whether engineers reason about why each move is safe rather than reciting the recipe.

**The scenario.** A ledger of transaction amounts is stored in ascending order, and a chargeback of exactly `T` must be explained by two entries. The brute-force answer checks every pair: two nested loops, O(n²) comparisons. The converging two-pointer technique replaces that with a single linear pass — but only because the ledger is sorted. **The mechanism.** Place `lo` at the first (smallest) entry and `hi` at the last (largest). Each iteration computes `s = a[lo] + a[hi]` and takes one of three actions: - `s == T`: a qualifying pair is found — done. - `s < T`: advance `lo` by one. - `s > T`: retreat `hi` by one. Loop while `lo < hi`. Each step moves exactly one pointer inward one position, so after at most `n - 1` moves the pointers meet and the scan ends: O(n) time, O(1) extra space. **Why sortedness is a correctness requirement, not a speed-up.** Consider the `s < T` case. Because the array is sorted, `a[hi]` is the largest element still inside the window `[lo, hi]`. If even `a[lo] + a[hi]` falls short of `T`, then `a[lo]` plus *any* element of the window falls short — the low element has been proven partnerless, and discarding it cannot lose an answer. The mirrored argument covers `s > T`: `a[lo]` is the smallest remaining, so if the sum is already too big, `a[hi]` can pair with nothing in the window. Every inward move is backed by this small proof. On unsorted data the proof evaporates. `a[hi]` is just some value, not the maximum of the window, so `a[lo] + a[hi] < T` says nothing about `a[lo]`'s other potential partners. A move made anyway might discard the exact element the answer needed — and the scan would then report "no pair" incorrectly. This is the core wrong belief to avoid: sorting is not an optimization that makes two pointers faster; it is the precondition that makes the moves valid at all. **Another wrong belief: "it's a heuristic."** Some candidates accept the linear pass but hedge that a quadratic check is still needed "to be sure". It is not. Each move discards only pairs proven impossible, so when the pointers meet without a match, every pair has been either examined or eliminated by proof. The scan is exact, not approximate. (The full invariant-style argument deserves its own treatment, but the one-line version: the answer, if one exists, always remains inside the current window.) **Cost accounting.** | approach | time | extra space | precondition | |---|---|---|---| | brute-force all pairs | O(n²) | O(1) | none | | sort, then converge | O(n log n) | sort-dependent | may reorder the data | | converge on sorted input | O(n) | O(1) | already sorted | If the data arrives sorted the pattern is essentially free. If not, sorting dominates the cost, and whether it is worthwhile depends on whether reordering is allowed and how many queries will amortize the sort. **Where the pattern generalizes.** Nothing here depends on sums specifically. The technique applies whenever the input's order makes each end-comparison a *decision*: a predicate over the pair that is monotone in each element, so a failed test at one end condemns that end's element outright. Verifying a mirror constraint from both ends of an ordered roster, closest-pair-to-target variants, and bounded-difference checks all reuse the same skeleton — one comparison, one provably safe inward move. **What interviewers listen for.** Naming the three-way decision is table stakes. The differentiator is spontaneously producing the safety argument — "the high end is the largest remaining, so a too-small sum condemns the low element" — because that shows you can justify each move rather than pattern-match the recipe. Follow-ups usually probe exactly that: why one move per step, what breaks unsorted, and what the scan proves when it ends empty-handed.

  • The input arrives unsorted — what does the two-pointer route cost end to end?
    Sorting first costs O(n log n), which then dominates the O(n) converging pass. Whether that is acceptable depends on whether you may reorder the data (or can afford a sorted copy) and how many queries will amortize the sort; when the data is already sorted, the pattern is essentially free.
  • Does the technique need random access, the way binary search does?
    No. It only ever reads the two current ends and steps inward one position at a time, so bidirectional sequential access suffices — a doubly-linked sequence works. Binary search, by contrast, needs O(1) jumps to arbitrary midpoints to keep its O(log n) bound.
  • Can both pointers ever need to move on the same comparison?
    Only on a match while enumerating all pairs: after recording, both must advance or the same pair repeats. On a non-matching comparison exactly one pointer moves — that one-move-per-step discipline is what gives the n-1-step bound and keeps every move individually justified.

Two clerks work a price-ordered shelf from opposite ends. If the cheapest plus the priciest item together cost too little, swapping the priciest for anything cheaper only lowers the total — the cheap item is hopeless and gets set aside.

saying these in an interview costs you the question

  • Claims two pointers works on unsorted arrays with no preprocessing
  • Treats sorting as a speed optimization rather than a correctness requirement
  • Says the pass halves the search space like binary search, giving O(log n)
  • Believes an O(n^2) all-pairs check is still needed afterwards to be sure

context

open as a page

In a same-direction two-pointer sweep over one array, why is the cost O(n) and not O(n^2)?

level: juniorimportance: must knowfreq 70%

basics

~20 s

Both 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.

open as a page

After one partition pass around a pivot value, what is guaranteed about the array?

level: juniorimportance: must knowfreq 72%

basics

~20 s

A 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.

open as a page

What loop invariant makes the converging-pointer pair-sum search on a sorted array exact — why can an inward move never skip the answer?

level: middleimportance: must knowfreq 62%

basics

~20 s

The 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.

open as a page

In an in-place sweep collapsing consecutive equal timestamps in a sorted log, what does the slow index mark?

level: middleimportance: must knowfreq 78%

basics

~20 s

Slow 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.

open as a page

In a three-way Dutch national flag partition, why must mid not advance after a swap with the high region?

level: middleimportance: must knowfreq 60%

basics

~20 s

Because the record swapped in from the high end has never been examined. A low-side swap brings back an element already scanned and classified, so mid may advance; skipping the newly arrived one would file it in the wrong region.

open as a page

In a triple-sum enumeration on sorted input (fix a[i], converge lo/hi on the rest), why does skipping i when a[i] == a[i+1] drop valid triples?

level: middleimportance: should knowfreq 46%

basics

~20 s

Skipping while the fixed value equals the next one processes only the last copy, whose search window holds no more copies — so triples needing two equal values are lost. Skip against the previous element instead, after the first occurrence is processed.

open as a page

Why does Lomuto's partition perform more swaps than Hoare's on duplicate-heavy input?

level: middleimportance: should knowfreq 44%

basics

~20 s

Lomuto swaps for every element that compares at most equal to the pivot — with many duplicates, nearly all of them. Hoare swaps only when both pointers have stopped on misplaced elements, fixing two positions per exchange.

open as a page

Why do converging pointers beat a hash-based pair search on a read-only sorted file of a billion 64-bit amounts, and what arithmetic trap remains?

level: seniorimportance: should knowfreq 38%

basics

~20 s

Converging pointers need O(1) extra memory and two sequential read fronts, so they work on a read-only billion-entry file where an O(n)-space hash structure will not fit. The remaining trap: adding two extreme 64-bit values can overflow and corrupt the comparison.

open as a page

Merging a sorted batch into a pre-sized buffer that already holds sorted data — why write from the back?

level: seniorimportance: should knowfreq 55%

basics

~20 s

Writing front-to-front, the write cursor catches up to entries not yet read: the first time the incoming batch wins a comparison, the write lands on a live slot and destroys it. Descending from the back keeps every write inside vacated space.

open as a page

After an in-place partition splits payroll rows into contractors and employees, is the original row order preserved?

level: seniorimportance: should knowfreq 36%

basics

~20 s

No. In-place partition schemes are unstable: they exchange rows across long distances, so rows within each group come out reordered. Preserving order costs O(n) extra space in one pass, or O(n log n) time in place.

open as a page

In-place destructive sweeps or a fresh output buffer — how do you set that policy for a team?

level: principalimportance: should knowfreq 34%

basics

~20 s

Decide by ownership and evidence, not taste. Allow a destructive sweep where a stage owns the buffer and a measured memory ceiling is real, with a loud contract; elsewhere prefer the copying version, which is asymptotically identical and cheaper to review.

open as a page