Prefix Sum
Apply range updates in O(1) by marking diff[l] += val and diff[r+1] -= val, then prefix sum to get final values. The inverse of prefix sum. Used for flight bookings, car pooling, and range addition.
You are given an array of flight bookings where each booking adds a certain number of seats to every flight in a contiguous range. With thousands of bookings and tens of thousands of flights, how do you compute the final seat count for each flight without grinding through every range one by one? This is LeetCode 1109. Corporate Flight Bookings, and it is the perfect introduction to the difference array technique.
The naive approach processes each booking by iterating through every index in its range and adding the value. If you have bookings and the array has elements, each booking could span the entire array, giving you time. When both and are on the order of , that is operations, far too slow.
The waste is obvious: if a booking says "add 10 to flights 2 through 5000," you are performing 4999 additions that all encode the same information. There must be a way to record that information in constant time.
Instead of modifying every element in the range , create a difference array diff and make just two updates:
diff[l] += val (the increment starts here)diff[r + 1] -= val (the increment stops after r)After processing all operations, compute the prefix sum of diff. The result at each index is the final value of that element.
Why does this work? The +val at position l means "from here onward, everything is val higher." The -val at position r+1 cancels that effect, so positions beyond r are unaffected. When you take the prefix sum, these two markers propagate exactly the right adjustment to exactly the right range.
To see how this works in LeetCode 1109, suppose we have flights (1-indexed) and these bookings:
We create a difference array of size (the extra slot avoids boundary checks):
diff = [0, 0, 0, 0, 0, 0] (indices 0 through 5, using 1-indexed flights)
Booking 1 (flights 1-3, val=10): diff[1] += 10, diff[4] -= 10
diff = [0, 10, 0, 0, -10, 0]
Booking 2 (flights 2-4, val=20): diff[2] += 20, diff[5] -= 20
diff = [0, 10, 20, 0, -10, -20]
Booking 3 (flights 2-5, val=25): diff[2] += 25, diff[6] is out of bounds, so we skip the subtraction (the effect lasts through the end).
diff = [0, 10, 45, 0, -10, -20]
Now take the prefix sum of diff starting from index 1:
Final answer: [10, 55, 55, 45, 25]. Each booking was processed in instead of .
Here is the solution for LeetCode 1109:
def corpFlightBookings(bookings, n):
diff = [0] * (n + 1)
for first, last, seats in bookings:
diff[first - 1] += seats
if last < n:
diff[last] -= seats
# prefix sum
for i in range(1, n):
diff[i] += diff[i - 1]
return diff[:n]Two passes: one over the bookings () and one prefix sum (). Total: .
Difference arrays and prefix sums are inverses of each other. If you take the prefix sum of an array and then compute the difference array of the result, you get the original array back, and vice versa.
Formally, if d[i] = a[i] - a[i-1] (with a[-1] = 0), then d is the difference array of a, and the prefix sum of d recovers a. This duality is why the difference array technique works: you record changes (differences), and a prefix sum reconstructs the values.
LeetCode 370. Range Addition is the textbook version. You start with an array of zeros and apply a series of [start, end, val] operations. Return the final array.
def getModifiedArray(length, updates):
diff = [0] * (length + 1)
for start, end, val in updates:
diff[start] += val
diff[end + 1] -= val
for i in range(1, length):
diff[i] += diff[i - 1]
return diff[:length]This is the difference array pattern in its cleanest form: no indexing offsets, no extra constraints. If you internalize this template, every other variant is just a small twist.
LeetCode 1094. Car Pooling asks: given trips where each trip is [numPassengers, from, to], and a vehicle with a fixed capacity, can you complete all trips without exceeding capacity?
Think of the timeline as an array indexed by location. Each trip is a range update: add passengers at from, remove them at to (they get off at to, so the subtraction is at to, not to + 1).
def carPooling(trips, capacity):
diff = [0] * 1001 # locations range 0 to 1000
for passengers, start, end in trips:
diff[start] += passengers
diff[end] -= passengers # passengers exit at 'end'
current = 0
for d in diff:
current += d
if current > capacity:
return False
return TrueNotice the subtlety: passengers leave at the to location, so we subtract at index to rather than to + 1. The problem defines the range as half-open: passengers are on board during . Always read the problem carefully to determine whether the range endpoint is inclusive or exclusive.
The technique extends to two dimensions. To increment every cell in a submatrix from to by val, you make four updates to a 2D difference array:
diff[r1][c1] += val
diff[r1][c2 + 1] -= val
diff[r2 + 1][c1] -= val
diff[r2 + 1][c2 + 1] += valAfter all operations, compute the 2D prefix sum to recover the final matrix. The logic is the same inclusion-exclusion principle used in 2D prefix sums, just applied in reverse.
def apply_2d_difference(n, m, operations):
diff = [[0] * (m + 1) for _ in range(n + 1)]
for r1, c1, r2, c2, val in operations:
diff[r1][c1] += val
diff[r1][c2 + 1] -= val
diff[r2 + 1][c1] -= val
diff[r2 + 1][c2 + 1] += val
# 2D prefix sum
for i in range(n):
for j in range(m):
if i > 0:
diff[i][j] += diff[i - 1][j]
if j > 0:
diff[i][j] += diff[i][j - 1]
if i > 0 and j > 0:
diff[i][j] -= diff[i - 1][j - 1]
return [row[:m] for row in diff[:n]]LeetCode 2536. Increment Submatrices by One is a direct application of this approach.
For the 2D variant, time is and space is .
Compared to the brute-force , the difference array reduces the cost of each range update from to , which is the entire point. It is one of the simplest and most satisfying optimizations in competitive programming.
You're probably looking at a difference array when:
Common templates:
diff[l] += v, diff[r + 1] -= v, prefix-sum to recover. Example: Range Addition.(time, delta) events, sort, and sweep, the same diff-array idea on a compressed axis. Example: My Calendar III.Practice Problems (15)