Skip to content
ΣDSA Patterns
Menu
Language

Pattern #08

Difference Array

Recommended

Range 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

  1. Allocate diff of length n (or n+1 if you need a clean R+1 slot).
  2. For each update [L, R] += v: diff[L] += v; if R+1 < n: diff[R+1] -= v.
  3. Prefix: for i in 1..n-1: diff[i] += diff[i-1] (or write into result).
  4. 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;
}