skip to content

Removing one element from an array: when may you swap with the last instead of shifting?

level: middleimportance: should knowfreq 50%

answer

  1. Closing the hole has two prices
  2. One keeps order, one keeps time
  3. Ask who reads this array in order
  4. Subsequence versus permutation
  5. Both disturb positions held elsewhere

basics

~20 s

Only when the array's order carries no meaning. Swapping the last element into the vacated slot is constant time but permutes the array; shifting the tail left costs Θ(n − i) and is the only order-preserving option.

solid answer

~50 s

Deleting the booking at index `i` leaves a hole, and the two repairs have different prices. Shifting elements `i+1 … n−1` one slot left closes the hole while preserving every surviving element's relative order — Θ(n − i) moves, worst case Θ(n) when you remove from the front. Moving the last element into slot `i` and shrinking the count closes the hole with one write, Θ(1), but it teleports one record from the end into the middle, so any order the array carried is gone. That makes swap-with-last legal exactly when order is not load-bearing: nothing renders in array order, nothing assumes insertion order, the array is not kept sorted, and nothing outside holds a position into it as a handle. If any of those hold, the O(1) removal is not a faster version of the same operation — it is a different operation with a different result.

go deeper

for a junior

Be ready to say that deleting from an array leaves a hole and that closing it by shifting moves every element above the gap. Know that removing the last element is the cheap case.

for a middle

Explain both repairs with their costs and state the exact condition that makes the constant-time one legal — that no reader of the array can observe its order.

for a senior

Demonstrate that you check the readers before the benchmark: rendering order, sorted invariants and stored positions. Mention that both strategies invalidate handles and how widely each one does so.

for a principal

Own the maintainability angle: an O(1) removal that silently permutes shared data is a correctness trap for the next person, so it needs the invariant written down where the array lives, not just in the removal function.

## Two removals, two results Cancel a booking held at index `i` in an array of n bookings. The slot has to stop being part of the live data, and there are exactly two cheap ways to arrange that. **Shift-left.** Copy `i+1` into `i`, `i+2` into `i+1`, and so on up to the last used slot, then decrement the count. Elements move: `n − i − 1`. The surviving records keep the exact order they had, so a sorted array stays sorted and an insertion-ordered array stays insertion-ordered. Cost is Θ(n − i) — constant when you remove the last booking, linear when you remove the first. **Swap-with-last.** Copy the last used element into slot `i`, then decrement the count. Elements move: one, regardless of n and i. Cost Θ(1). Every surviving record is still present, but one of them has changed position, so the sequence is a *permutation* of what it was, not a subsequence of it. That difference — subsequence versus permutation — is the whole decision. It is not a performance tradeoff between two implementations of "remove"; it is two operations that happen to share a name. ## When order is not load-bearing Swap-with-last is safe when nothing downstream can observe the permutation. In practice that means checking four things about the array: 1. **Nothing renders it in stored order.** If cancelled-booking cleanup silently reshuffles the confirmation list a user is looking at, the bug shows up as "the rows jump around", which is reported late and diagnosed slowly. 2. **Nothing is kept sorted here.** If the array is maintained in start-time order so that scans can stop early, a single swap breaks the invariant that code relies on, and the failure appears far from the removal. 3. **No comparison or grouping depends on original order.** Any downstream step whose result differs when equal-ranking records swap places is order-dependent, even if nobody wrote that requirement down. 4. **No position is held elsewhere as a handle.** Both strategies invalidate stored positions, but differently, and that is worth stating precisely because it is where the O(1) claim most often quietly fails. ## The stored-position problem Suppose some other part of the system keeps "the booking at index 12" as a reference. After a **shift-left** at index 5, every index above 5 is off by one — every stored handle in the tail is now silently wrong, which is a catastrophic, wide invalidation. After a **swap-with-last**, exactly one handle is wrong: the one that pointed at the old final slot, whose record now lives at `i`. That narrowness is what makes the technique workable in systems that must track positions: a single handle can be repaired in constant time if you maintain a reverse mapping from record to position and update it on the swap. So the correct summary is not "shifting is safe and swapping is dangerous". It is that shifting preserves *order* and destroys *positions in bulk*, while swapping destroys *order* and disturbs exactly one position. Which of the two you can afford depends on what the rest of the system reads. ## Removing by identity, not by index A claim of O(1) removal assumes you already hold `i`. If the request is "cancel booking #4482" and you must scan the array to locate it, that scan costs Θ(n) and dominates whichever repair you pick — the constant-time swap saves nothing on the total. Interviewers probe here deliberately, because "removal is O(1)" stated without the precondition is the same error as claiming constant-time access after paying for a linear search to find the index. State the precondition before you state the cost. ## Capacity and the tail slot Neither removal shrinks the underlying array; a fixed-size array's capacity is a property of the allocation, not of how many slots are in use. Both strategies work by decrementing a live-count and leaving the trailing slot outside the live region. If the elements are references to larger objects, that abandoned slot may still be holding one alive; deliberately clearing the vacated tail slot is a small, cheap habit that avoids retaining data nobody can reach any more. ## Saying it correctly Say: shifting left is Θ(n − i) and preserves relative order; swap-with-last is Θ(1) and does not; choose by asking whether any reader of this array can observe order, and remember both costs assume the index is already known. Then name the one consequence a weaker answer leaves out — that stored positions are invalidated either way, broadly by the shift and narrowly by the swap.

  • Does shifting left after a removal keep a sorted array sorted?
    Yes. Shifting preserves the relative order of every surviving element, so removing one record from a sorted array leaves a sorted array — the result is a subsequence of the original. Swap-with-last does not: it moves the final element into the middle, so the array is a permutation of the survivors and any sorted invariant is broken immediately, usually without any error at the removal site.
  • Another component stores positions into this array as handles. What does each strategy do to them?
    Both invalidate handles, at very different scales. A shift-left at index i makes every stored position above i off by one, so the whole tail is silently wrong. A swap-with-last invalidates exactly one: the handle pointing at the old last slot, whose record now sits at i. That single case can be repaired in constant time if you keep a reverse map from record to position and update it during the swap.
  • Is swap-with-last removal still O(1) if you are given the booking reference rather than the index?
    No. Locating the record by reference in an unsorted array is a linear scan, and that scan dominates: Θ(n) to find plus Θ(1) to remove is Θ(n) overall. The constant-time claim only holds when the caller already has the position — for example because it just iterated to it, or because a separate structure maps references to positions and is kept in step with the array.

saying these in an interview costs you the question

  • Calls swap-with-last a strictly faster removal with no downside
  • Assumes shifting left is needed even when order is meaningless
  • Claims removal is O(1) while ignoring the scan that found the index
  • Thinks removing an element shrinks the array's capacity
  • Says a sorted array survives a swap-with-last removal
  • Overlooks that shifting invalidates every stored position above the hole

context