Overview
A difference array lets you add a value to an entire range in O(1). Instead of updating every element in [l, r], you record the change at the start (diff[l] += v) and cancel it after the end (diff[r + 1] -= v). A single prefix sum over the difference array at the end reconstructs the final values.
It is the inverse of prefix sums: prefix sums make range queries fast, difference arrays make range updates fast. Use it whenever many range updates happen before you read the results.
Instead of writing '+1 guest' on every day of a trip, you write '+1' on the arrival day and '-1' on the day after departure. Walking through the calendar and keeping a running total tells you how many guests are present each day.
When to use it
- Many range increments, followed by reading all values once.
- Counting how many intervals cover each point (bookings, trips, meetings).
- Line sweep: +1 when something starts, -1 when it ends.
- 2D versions: add a value to many sub-rectangles of a grid.
Problem patterns it solves
Recognize it when: apply many [l, r, +v] updates, then return the array.
- 370. Range Addition
- 1109. Corporate Flight Bookings
- 1854. Maximum Population Year
Recognize it when: passengers or bookings over time must not exceed a limit.
- 1094. Car Pooling
- 732. My Calendar III
- 2406. Divide Intervals Into Minimum Number of Groups
Recognize it when: how many intervals cover each point; points covered by at least k.
- 2848. Points That Intersect With Cars
- 1893. Check if All Integers in a Range Are Covered
- 253. Meeting Rooms II (sweep version)
Recognize it when: increment many rectangles in a grid.
- 2536. Increment Submatrices by One
- 850. Rectangle Area II (sweep)
Where it is used in real software
Booking systems compute occupancy per night from arrival and departure events using the same +1 / -1 sweep.
Cloud schedulers compute concurrent usage of CPUs or licenses over time from start and end events.
Finding times when all participants are free is a sweep over +1 / -1 busy events.
2D difference arrays apply many rectangular brightness adjustments in O(1) each before one final pass.
Key terms
- diff[i]
- arr[i] - arr[i - 1]: how much the value changes at index i.
- Range update
- diff[l] += v and diff[r + 1] -= v.
- Reconstruction
- A prefix sum over diff gives the final array.
- Line sweep
- Process start and end events in coordinate order, maintaining a running count.
How it works, step by step
- 1Allocate n + 1 slots
The extra slot absorbs diff[r + 1] when r is the last index.
- 2Apply each update in O(1)
For [l, r, v]: diff[l] += v; diff[r + 1] -= v.
- 3Prefix sum once
running += diff[i]; result[i] = running.
- 4Add the original array if needed
If the array was not all zeros, add result[i] to the original values.
STEP 1diff has n + 1 = 6 slots, all zero.
1109. Corporate Flight Bookings
bookings = [[1, 2, 10], [2, 3, 20], [2, 5, 25]], n = 5 flights (1-indexed)
| Booking | diff update | diff[1..6] after |
|---|---|---|
| [1, 2, 10] | diff[1] += 10, diff[3] -= 10 | 10, 0, -10, 0, 0, 0 |
| [2, 3, 20] | diff[2] += 20, diff[4] -= 20 | 10, 20, -10, -20, 0, 0 |
| [2, 5, 25] | diff[2] += 25, diff[6] -= 25 | 10, 45, -10, -20, 0, -25 |
| Prefix sum | running totals | 10, 55, 45, 25, 25 |
NOWBooking: [1, 2, 10] | diff update: diff[1] += 10, diff[3] -= 10 | diff[1..6] after: 10, 0, -10, 0, 0, 0
Answer [10, 55, 45, 25, 25]. With b bookings and n flights, the cost is O(b + n) instead of O(b x n).
Implementation
function applyRangeUpdates(n, updates) { const diff = new Array(n + 1).fill(0); for (const [l, r, v] of updates) { diff[l] += v; diff[r + 1] -= v; } const result = new Array(n); let running = 0; for (let i = 0; i < n; i++) { running += diff[i]; result[i] = running; } return result;} // 1094. Car Pooling: never exceed capacityfunction carPooling(trips, capacity) { const diff = new Array(1001).fill(0); for (const [passengers, from, to] of trips) { diff[from] += passengers; diff[to] -= passengers; // passengers leave at 'to', so no +1 } let onboard = 0; for (const change of diff) { onboard += change; if (onboard > capacity) return false; } return true;} // Sweep with sorted events when coordinates are largefunction maxOverlap(intervals) { const events = []; for (const [start, end] of intervals) events.push([start, 1], [end, -1]); events.sort((a, b) => a[0] - b[0] || a[1] - b[1]); // end before start at ties let current = 0, best = 0; for (const [, delta] of events) { current += delta; best = Math.max(best, current); } return best;}Complexity and performance
Two writes (four in 2D).
One prefix sum pass.
vs O(q x n) naive.
When coordinates are too large for an array.
Trade-offs
You must finish all updates before reading. If reads and updates interleave, use a Fenwick tree or segment tree with lazy propagation.
An array indexed by coordinate needs memory proportional to the range; for large ranges, sort events or use a TreeMap.
Variants and related techniques
Sort (position, delta) pairs and scan; handles coordinates up to 10^9.
Java TreeMap<Integer, Integer> keeps deltas sorted for online calendar problems (My Calendar III).
Four corner updates per rectangle, then a 2D prefix sum.
Common mistakes
- Array of size n instead of n + 1.
Fix: diff[r + 1] must exist even when r = n - 1.
- Inclusive vs exclusive end.
Fix: For [from, to) intervals like car pooling, subtract at to, not to + 1.
- Tie order in sweeps.
Fix: Decide whether an end at time t frees capacity before a start at t, and sort accordingly.
Interview questions
How are difference arrays related to prefix sums?
They are inverses. The prefix sum of a difference array gives the original array, and the difference of a prefix sum array gives the original values back.
When would you use a segment tree instead?
When queries and range updates are interleaved online. A segment tree with lazy propagation supports both in O(log n).
Practice problems
| Problem | Difficulty | What it trains |
|---|---|---|
| 370. Range Addition | Medium | Basic template. |
| 1109. Corporate Flight Bookings | Medium | 1-indexed ranges. |
| 1094. Car Pooling | Medium | Half-open intervals and capacity. |
| 1854. Maximum Population Year | Easy | Coverage peaks. |
| 2536. Increment Submatrices by One | Medium | 2D difference. |