skip to content

In a divide-and-conquer closest-pair search over drop coordinates, what must the combine step do?

level: seniorimportance: should knowfreq 38%

answer

  1. The halves are not the whole story
  2. What about a pair straddling the line?
  3. Use the sub-answers to bound the search
  4. Only a narrow band can beat d
  5. Order the band, stop after a few

basics

~20 s

The combine step must check pairs that straddle the dividing line, since the closest pair overall may have one point on each side. It stays cheap by using the recursion's own distance to bound the search to a narrow band.

solid answer

~40 s

Split the drops by a vertical line at the median x-coordinate, recurse on each side, and let `d` be the smaller of the two answers. The combine step cannot just return `d`: the true closest pair may straddle the line. But it also must not compare every left point with every right point, or the merge alone is quadratic and the recursion buys nothing. The trick is to let the sub-answers prune: only points within horizontal distance `d` of the line can possibly beat `d`. Walk that band in y-order and compare each point against a constant number of successors — the classic bound is seven — because points already at least `d` apart cannot crowd a `d`-by-`2d` box. That makes the combine linear, and the whole search linearithmic.

go deeper

for a junior

You are not expected to derive this. Know that a decomposition must account for answers that cross the boundary between the pieces, and that ignoring the seam is a correctness bug, not a performance one.

for a middle

Be able to explain why the smaller of the two half-answers is not the final answer, and why an all-pairs check across the boundary would make the whole recursion pointless.

for a senior

Walk the design end to end unprompted: the band of width d, the y-ordering, the constant-successor bound, and where the y-ordering comes from so the combine stays linear rather than log-linear.

for a principal

Own the generalisable rule — a combine step must consume the bound its recursive calls produced — and be ready to argue whether this algorithm's correctness risk is worth its win at the input sizes your service actually handles.

## The setup You have a set of points in the plane — say the drop coordinates on a delivery run — and you want the two that are closest to each other. The brute-force answer compares every pair: `Θ(n²)`. The divide-and-conquer design is the standard way to beat it, and it is worth studying not for the result but because **the combine step is the entire design**. The divide step is trivial and the conquer step is a recursive call; everything interesting happens on the way back up. ## Divide and conquer **Divide:** sort the points by x-coordinate once, up front, and split at the median into a left set and a right set of roughly equal size, separated by a vertical line at `x = xm`. **Conquer:** recurse on each side, obtaining `dLeft` and `dRight`, the closest-pair distances within each half. Let `d = min(dLeft, dRight)`. The two halves are disjoint sets of points, so the subproblems are genuinely independent: nothing computed on the left is needed on the right, and no subproblem is ever solved twice. ## Why the combine cannot just return d `d` is the best distance among pairs *both of whose points lie on the same side*. Nothing has yet examined a pair with one point on the left and one on the right, and such a pair can easily be closer — two drops on opposite sides of the same street, with the dividing line between them. Returning `min(dLeft, dRight)` is the single most common wrong answer, and it is wrong on inputs as small as three points. ## Why the combine must not be exhaustive either The obvious fix — compare every left point with every right point — is correct and useless. That is `Θ(n²)` work at the top level alone, which by itself dominates the entire recursion. A quadratic combine turns a decomposition into a slower version of brute force. This is the general lesson of the paradigm in one example: **if the combine step ignores what the recursion learned, the recursion was pointless.** ## The pruning argument The recursion already produced a bound, and the combine step's job is to exploit it. 1. **Restrict to a band.** Any straddling pair closer than `d` must have both points within horizontal distance `d` of the dividing line — otherwise their x-difference alone already exceeds `d`. So only points in the vertical strip `[xm - d, xm + d]` are candidates. In the worst case every point is in the strip, so this step alone does not bound anything. 2. **Order the band by y.** Now walk the strip's points in increasing y-coordinate. For each point, only points whose y-coordinate is within `d` above it can possibly be closer than `d`, so you can stop scanning forward as soon as the y-gap exceeds `d`. 3. **Bound the scan with geometry.** The candidates for a given point live in a `2d`-wide, `d`-tall rectangle straddling the line. Split that rectangle into squares of side `d/2`: each square can hold at most one point, because two points in the same square would be closer than `d` and would already have been found within one half. That caps the number of candidates a point must be compared against at a small constant — the classic argument gives at most seven successors in y-order. So the strip scan is `Θ(n)` comparisons, not `Θ(n²)`, and the bound is a geometric fact rather than an assumption about the data. ## The cost, and the one bookkeeping trap With a linear combine and two half-size subproblems, the total is `Θ(n log n)`. But that holds only if the y-ordering is available for free. If you re-sort the strip by y at every level, the combine becomes `Θ(n log n)` per level and the total degrades to `Θ(n log² n)` — still far better than quadratic, but not the advertised bound. The standard fix is to have each recursive call return its points in y-order and merge the two ordered halves on the way up, exactly as a merge step would, so the ordering is maintained in linear time per level. That detail is a good senior signal: it shows you tracked where the sortedness comes from rather than assuming it. ## What the interviewer is really testing Three things, in order of weight: that you noticed the straddling case at all; that you refused the quadratic merge and looked for a bound; and that you found the bound *in the sub-answers themselves*. That last move — the recursion's result constrains the combine's search space — is the reusable idea. When you meet an unfamiliar problem and the combine step looks quadratic, the question to ask is always "what did the recursive calls already prove, and how does that shrink what I still have to check?"

  • Why does the strip scan stay linear instead of degenerating to quadratic?
    Geometry bounds it. A candidate for a given point must lie in a `2d`-by-`d` rectangle around the dividing line, and that rectangle can be cut into squares of side `d/2` holding at most one point each, since two points in one square would already have been found within a half. So each point compares against a constant number of successors in y-order.
  • What happens to the total cost if you re-sort the band by y at every level?
    The combine becomes `Θ(n log n)` per level and the total slips to `Θ(n log² n)`. It is still a large win over quadratic, but the standard fix is to have each recursive call return its points already in y-order and merge the two ordered halves on the way up, keeping the combine linear.
  • What is the general design lesson here for any combine step?
    The sub-answers should constrain the combine's search space. If the merge ignores what the recursion proved and re-examines everything, its cost dominates and the decomposition buys nothing. Whenever a combine step looks quadratic, ask what bound the recursive calls already established.

Two survey teams each report the closest pair of markers inside their own half of a map. Before you trust the smaller of the two numbers, you still have to inspect the seam, where a pair can sit on opposite sides of the boundary.

saying these in an interview costs you the question

  • Returns the smaller of the two halves' answers as the final result
  • Compares every left point against every right point
  • Thinks choosing the split line is the hard part of the design
  • Scans the boundary band without ordering it by y
  • Assumes any correct combine step preserves the n log n bound

context