⚡ Play a quiz
HomeLearnData Structures & AlgorithmsArrays › Prefix sum
Lesson 5 of 5 · Arrays

Prefix Sum Arrays and Range Queries

Arrays100%

If a problem asks the same kind of question about many different ranges, precompute. A prefix sum array trades O(n) of setup and O(n) of memory for range-sum queries that answer in constant time — and the same idea, paired with a hash map, solves a whole family of "count the subarrays" problems.

Read time
8 min
Track
Data Structures & Algorithms
Sections
3
Practice
5

Building the prefix array

prefix[i] holds the sum of the first i elements. Using a length of n+1 and keeping prefix[0] = 0 removes every special case for ranges that start at index 0 — worth doing every time.

Prefix sums and O(1) range queries
int[] buildPrefix(int[] a) {
    int[] prefix = new int[a.length + 1];   // prefix[0] = 0
    for (int i = 0; i < a.length; i++) {
        prefix[i + 1] = prefix[i] + a[i];
    }
    return prefix;
}

// Sum of a[l..r] inclusive, in O(1)
int rangeSum(int[] prefix, int l, int r) {
    return prefix[r + 1] - prefix[l];
}
a = [3, 1, 4, 1, 5], prefix = [0, 3, 4, 8, 9, 14]
QueryComputationResult
sum(0, 2)prefix[3] - prefix[0] = 8 - 08
sum(1, 3)prefix[4] - prefix[1] = 9 - 36
sum(2, 4)prefix[5] - prefix[2] = 14 - 410

Building costs O(n) once. After that, q queries cost O(q) instead of O(q x n) — the whole point when a problem hands you thousands of queries over one fixed array.

a 31415 [0][1][2][3][4] prefix 034 8914 prefix[1] prefix[4] sum(a[1..3]) = prefix[4] - prefix[1] = 9 - 3 = 6 one subtraction, whatever the range length → O(1) per query
Any range sum becomes one subtraction: the running total up to the end, minus the running total before the start.

Prefix sum + hash map

"How many subarrays sum to k?" A subarray (i, j] sums to k exactly when prefix[j] - prefix[i] = k, which rearranges to prefix[i] = prefix[j] - k. So while scanning, ask how many earlier prefixes had the value current - k — a hash map answers that in O(1).

Count subarrays with sum exactly k
int countSubarrays(int[] a, int k) {
    Map<Integer, Integer> seen = new HashMap<>();
    seen.put(0, 1);              // the empty prefix, so subarrays from index 0 count

    int running = 0, count = 0;
    for (int value : a) {
        running += value;
        count += seen.getOrDefault(running - k, 0);
        seen.merge(running, 1, Integer::sum);
    }
    return count;
}
warn

Do not forget seen.put(0, 1)

Without that seed, every subarray that starts at index 0 is missed, and the answer comes back too low on exactly the inputs a test suite checks first. It represents the empty prefix — the sum before any element is consumed.

This version is O(n) time and O(n) space, it handles negative numbers correctly, and it is the standard answer when a sliding window fails for that reason.

Variants worth knowing

  • Prefix XOR — same structure with XOR instead of addition; solves "count subarrays with XOR equal to k".
  • Prefix count — store a running count of a property (vowels, even numbers) to answer "how many X in this range".
  • 2D prefix sums — an (n+1) x (m+1) grid answers any rectangle sum with four lookups and inclusion-exclusion.
  • Difference array — the inverse idea: apply many range updates in O(1) each, then a single prefix pass materialises the final array.

Key takeaways

  • Precompute once, answer many range queries in O(1) each.
  • Keep prefix[0] = 0 and use length n+1 to avoid special-casing index 0.
  • prefix + hash map counts subarrays with a target sum in O(n), negatives included.
  • A difference array is the mirror image: cheap range updates, one pass to finalise.

Practice

ProblemPatternLevel
Range sum query on an immutable arrayPrefix sumEasy
Find the pivot indexPrefix sumEasy
Subarray sum equals kPrefix + hash mapMedium
Contiguous array of equal 0s and 1sPrefix + hash mapMedium
Range sum query on a 2D matrix2D prefix sumMedium

Frequently asked questions

What is a prefix sum array?

An array where each position holds the sum of all elements before it. It lets any range sum be computed as the difference of two prefix values, in constant time.

When should I use prefix sums instead of a sliding window?

When the array contains negative numbers, or when there are many range queries over an array that does not change. Sliding window relies on the sum moving predictably as the window shrinks, which negatives break.

What is a difference array?

The inverse of a prefix sum. Range updates are recorded as two O(1) edits at the range boundaries, and one prefix-sum pass at the end applies every update at once.

Test yourself on Arrays

Reading is not recall. Take a timed quiz on this topic solo, or share a room code and battle friends on it.

⚡ Start the Arrays quiz

More in Arrays