Corporate Flight Bookings is the cleanest introduction to the difference array — a trick that turns "add the same value to a whole range" from an O(range) chore into just two writes, no matter how wide the range is.
Problem. There are n flights, numbered 1 to n. Each booking reserves a number of seats on
every flight in a contiguous range (from a first flight through a last flight, inclusive). After all
bookings are applied, report the total seats reserved on each individual flight.
Example: n = 4, bookings = [[1, 2, 5], [2, 4, 10], [1, 4, 3]] → answer [8, 18, 13, 13].
Flight 2 is covered by all three bookings, so it gets 5 + 10 + 3 = 18.
The slow way first
The literal reading: for each booking, loop over every flight from first to last and add seats. That works, but if a booking covers a huge range you touch every flight in it, and with many wide bookings the total work blows up to O(n × bookings) — far too slow.
The question to ask: each booking changes a contiguous run by the same amount — can I record the change without walking the whole run? Yes. A range update is fully described by where it starts and where it stops, so we only need to mark those two endpoints.
The idea: store changes, not totals
Keep an array diff of deltas instead of totals. To add seats across flights first..last:
diff[first - 1] += seats— "from here on, addseats."diff[last] -= seats— "and stop adding it after this flight."
Each booking is two writes, regardless of range width. Once every booking is recorded, walk diff left to right keeping a running prefix sum: the value at each position is that flight's true total. The -= seats at last exactly cancels the earlier += seats, so the bump only covers first..last.
We use n + 1 slots so a booking ending at flight n has a harmless overflow slot for its -= seats — that slot is never returned.
Walk through it
Step through the animation. For each booking the l pointer marks first - 1 (where seats are added) and the r+1 pointer marks last (where they are removed). After all three bookings, diff = [8, 10, -5, 0, -13]. Then the i pointer sweeps left to right, accumulating the running total so each cell becomes its flight total: [8, 18, 13, 13].
Pseudocode
make diff = array of n+1 zeros
for each booking [first, last, seats]:
diff[first - 1] += seats # start adding seats here
diff[last] -= seats # stop adding them after "last"
running = 0
for i from 0 to n-1:
running += diff[i] # prefix sum = true total
answer[i] = running
return answerThe Python solution
def corp_flight_bookings(bookings, n):
diff = [0] * (n + 1)
for first, last, seats in bookings:
l = first - 1
diff[l] += seats
diff[last] -= seats
answer = []
running = 0
for d in diff[:n]:
running += d
answer.append(running)
return answerdiffhasn + 1slots so the-= seatsatlast == nlands in a scratch slot we never return.- For each booking,
diff[l] += seatsopens the bump at flightfirstanddiff[last] -= seatscloses it — two writes, range width irrelevant. - Lines 5-6 are the whole trick: a range update done in O(1).
- The second loop is the prefix sum.
runningcarries the accumulated effect of all bumps that are still open at this flight, sorunningis exactly that flight's total. - We slice
diff[:n]so the overflow slot is dropped from the answer.
Complexity
| Case | Time | Notes |
|---|---|---|
| Brute force (fill each range) | O(n × bookings) (moderate) | touch every flight in every range |
| Difference array (this solution) | O(n + bookings) (moderate) | two writes per booking, one sweep |
O(n) (moderate)Each booking costs O(1) instead of O(range), and the final prefix-sum sweep is one pass over n. That trade — record only the endpoints of a range change, then prefix-sum once — is the core of the difference-array pattern.
When this pattern shows up
Any time a problem says "add the same amount to every element in a range" and asks for the final array
after many such updates, reach for a difference array: mark +v at the start and -v just past the
end, then prefix-sum. Range-increment problems, "car pooling," and interval-coverage counts are all the
same move.
Off-by-one is the trap. The -= goes at index last (not last - 1) because last is 1-based and the
removal must take effect on the flight after the range ends. Size the array n + 1 so a booking ending
at flight n has a valid slot to write that -= seats.
Practice
After recording all three bookings, diff = [8, 10, -5, 0, -13]. What is the running prefix sum when the sweep reaches flight 3 (index 2)?
1. Why is the difference-array approach faster than filling each range directly?
2. For a booking [first, last, seats], where does the subtraction go?
3. What turns the array of deltas into per-flight totals?
4. Why is the diff array sized n + 1 instead of n?