Pattern #08
Difference Array
RecommendedRange updates in O(1); rebuild the array with a prefix pass.
When to use
Many updates add a value to an entire range [L, R], then you need the final array or range queries after updates.
Recognition cues
- Add val to every index in [L, R] (many times)
- Corporate flight bookings / range addition
- Difference array then prefix restore
Common pitfalls
- Off-by-one on R+1 when marking the end of a range
- Forgetting the final prefix pass before reading values
- Using this when you need true segment-tree style mixed queries mid-stream
90-second recognition drill
Which pattern fits best?
- Add val to every index in [L, R] (many times)
- Corporate flight bookings / range addition
- Difference array then prefix restore
Interactive
Mental model
A full worked walkthrough of the invariant. Pause, scrub the dots, or use ← →. Aim to narrate each step yourself.
Step 1 of 8
0
0
0
0
0
0
diff starts at zeros
Range updates without touching every cell.
How to think about it
Instead of updating every cell in a range, write +v at L and -v at R+1 on a diff array. After all updates, a single prefix sum rebuilds the values. Each update is O(1); rebuild is O(n).
Template shapes
| Shape | Core move | Notes |
|---|---|---|
| Range add | diff[L]+=v; diff[R+1]-=v | Then prefix |
| Multiple updates | Batch all range ops first | One rebuild |
| 0-index vs 1-index | Be consistent on bounds | R+1 may be n |
Complexity baseline
O(1) per range update, O(n) to materialize. Space O(n) for the diff array.
From template to problem
- Allocate diff of length n (or n+1 if you need a clean R+1 slot).
- For each update [L, R] += v: diff[L] += v; if R+1 < n: diff[R+1] -= v.
- Prefix: for i in 1..n-1: diff[i] += diff[i-1] (or write into result).
- Read answers from the rebuilt array.
Template
Same skeleton in TypeScript, Python, and C#. Adapt the invariant; keep the structure.
Difference Array · Template
/** Difference array template: range add then prefix rebuild. */
export function applyRangeUpdates(n: number, updates: number[][]): number[] {
const diff = new Array(n + 1).fill(0);
for (const [l, r, val] of updates) {
diff[l!]! += val!;
if (r! + 1 < diff.length) diff[r! + 1]! -= val!;
}
const out = new Array<number>(n);
let run = 0;
for (let i = 0; i < n; i++) {
run += diff[i]!;
out[i] = run;
}
return out;
}
/** Difference array template: range add then prefix rebuild. */
export function applyRangeUpdates(n: number, updates: number[][]): number[] {
const diff = new Array(n + 1).fill(0);
for (const [l, r, val] of updates) {
diff[l!]! += val!;
if (r! + 1 < diff.length) diff[r! + 1]! -= val!;
}
const out = new Array<number>(n);
let run = 0;
for (let i = 0; i < n; i++) {
run += diff[i]!;
out[i] = run;
}
return out;
}
#StatusProblemTypeDifficultyDone
- 1#370 Range AdditionGuidemedium
- 2#1094 Car PoolingGuidemedium
- 3#1109 Corporate Flight BookingsGuidemedium
- 4#1893 Check if All the Integers in a Range Are CoveredGuideeasy
- 5#1943 Describe the PaintingGuidemedium
- 6#2381 Shifting Letters IIGuidemedium