Arrays · Core Array Techniques

Prefix Sums

Precomputing cumulative sums so any range-sum query answers in O(1) instead of rescanning the range.

  • 5 min read
  • 9 practice questions
  • 2 graded problems
On this page
  1. Description
  2. The approach
  3. A second flavor: prefix sum + hash map
  4. Where you'll see it
  5. Which tool for which job?
  6. Common mistakes
  7. Check yourself
  8. Key takeaways
  9. Quick revise
  10. Practice

Description

A prefix sum is the running total of an array: prefix[i] is the sum of the first i elements. Build it once in O(n), and the sum of any range becomes a single subtraction. Without it, every "sum of nums[l..r]" question adds the range up again, O(n) per query. Paired with a hash map, the same running total also finds subarrays that add up to a given value in one pass. That works even with negative numbers, where a sliding window fails.

We'll go from simple to more technical:

  1. The pattern: a padded prefix array and one subtraction per query.
  2. Prefix sum plus a hash map: subarrays that sum to k.
  3. Where the same idea runs in production (cumulative reports, rollups).
  4. When it applies, and when updates make it the wrong tool.

The approach

Make the prefix array one longer than the input and set prefix[0] = 0. Then prefix[i + 1] = prefix[i] + nums[i]. The sum of nums[l..r] is everything up to r, minus everything before l.

For nums = [2, -1, 3, 4, -2]:

i012345
nums[i]2-134-2
prefix[i]021486

The sum of nums[1..3] is prefix[4] - prefix[1] = 8 - 2 = 6, which is -1 + 3 + 4.

Java

int[] prefix = new int[nums.length + 1];   // prefix[0] = 0 by convention
for (int i = 0; i < nums.length; i++) {
    prefix[i + 1] = prefix[i] + nums[i];
}
// sum of nums[l..r] inclusive:
int rangeSum = prefix[r + 1] - prefix[l];

Python

prefix = [0] * (len(nums) + 1)   # prefix[0] = 0 by convention
for i, x in enumerate(nums):
    prefix[i + 1] = prefix[i] + x
# sum of nums[l..r] inclusive:
range_sum = prefix[r + 1] - prefix[l]

The extra prefix[0] = 0 is what lets a range start at index 0 without a special case.

A second flavor: prefix sum + hash map

Some questions aren't "build once, answer many queries". The longest subarray that sums to exactly k walks the array once. At each index it asks: did some earlier prefix sum to exactly sum - k? If so, the elements between that point and here add up to k.

Java

Map<Integer, Integer> firstIndexOfSum = new HashMap<>();
firstIndexOfSum.put(0, -1);           // an empty prefix (before index 0) sums to 0
int sum = 0, best = 0;
for (int i = 0; i < nums.length; i++) {
    sum += nums[i];
    if (firstIndexOfSum.containsKey(sum - k)) {
        best = Math.max(best, i - firstIndexOfSum.get(sum - k));
    }
    firstIndexOfSum.putIfAbsent(sum, i);   // keep the EARLIEST index for a given prefix sum
}

Python

first_index_of_sum = {0: -1}     # an empty prefix (before index 0) sums to 0
total = best = 0
for i, x in enumerate(nums):
    total += x
    if total - k in first_index_of_sum:
        best = max(best, i - first_index_of_sum[total - k])
    first_index_of_sum.setdefault(total, i)   # keep the EARLIEST index for a given prefix sum

Take the same array and k = 5. At index 4 the running sum is 6. The prefix up to index 1 summed to 1, which is 6 - 5. So [3, 4, -2], from index 2 to 4, sums to 5, and the best length is 3. The map keeps only the earliest index for each sum, because an earlier start gives a longer subarray.

Where you'll see it

Any "total as of date X" report is a prefix sum over a table sorted by time: a running account balance, or cumulative signups by day. Analytics systems keep precomputed rollup tables for the same reason. The idea is identical; only the storage is a database instead of an array.

Which tool for which job?

You needUse
Many range sums over an array that doesn't changea prefix-sum array
Subarrays summing to k (negatives allowed)prefix sum + hash map
Subarrays whose sum is divisible by kprefix sum mod k + hash map
Many range updates, then readsa difference array
Range sums with frequent point updatesa Fenwick tree (O(log n) each)
Sums of rectangles in a grida 2D prefix sum

Common mistakes

MistakeWhat happensDo this instead
Rebuilding the prefix array per queryright answers, O(n) per querybuild once, before the queries
No prefix[0] = 0 paddingspecial cases for ranges starting at 0size it n + 1
Mixing inclusive and exclusive roff-by-one sumsprefix[r + 1] - prefix[l] for inclusive r
No {0: -1} (or {0: 1}) seed in the mapsubarrays starting at index 0 are missedseed the empty prefix
An int prefix array in Javaoverflow on large totalslong[]

Check yourself

Try to answer before opening each one - recalling beats re-reading.

1. A solution rebuilds the prefix array inside the query loop. Every test passes. Is it a good solution?

Show answer

Not necessarily. The answers are right, but each query costs O(n) instead of O(1). Tests that only check answers won't notice unless they're big enough to make the slow version time out. Passing tests shows the code is correct, not that the approach is right.

2. Why does the hash map start with {0: -1}?

Show answer

So a subarray that starts at index 0 can be found. If the running sum at index i equals k, then sum - k is 0. The entry for sum 0 at index -1 stands for "before the array starts", and the length i - (-1) = i + 1 covers the whole prefix.

3. The array changes often between range-sum queries. Should you still use a prefix array?

Show answer

Probably not. Each change costs O(n) to fix the prefix sums, which defeats the point. A Fenwick tree (also called a binary indexed tree) handles both updates and range sums in O(log n) each.

Key takeaways

  • Build the prefix array once in O(n). Then every range sum is O(1): prefix[r + 1] - prefix[l].
  • The padding prefix[0] = 0 removes the special case for ranges that start at index 0.
  • Prefix sum plus a map of the earliest index per sum finds subarrays that sum to k in one pass, negatives included.
  • Passing every test proves correctness, not the right approach.
  • When the array changes often, use a Fenwick tree instead.

Quick revise

The whole skill on one page, for the night before an interview.

Everything from the lesson and the deep dive on one page. Skim it before practice or an interview, and open the full lesson for anything that doesn't ring a bell.

Pick the tool

You needUse
Many range sums, static arraya prefix array of size n + 1
Longest subarray summing to kprefix + map of earliest index, seeded {0: -1}
Number of subarrays summing to kprefix + map of counts, seeded {0: 1}
Sums divisible by kremainders, floorMod in Java
Many range updatesa difference array
Updates and queries interleaveda Fenwick tree
Rectangle sums2D prefix sums

Snippets worth knowing by heart

Java

Map<Long, Integer> seen = new HashMap<>(Map.of(0L, 1));   // the empty prefix
long sum = 0;
int count = 0;
for (int x : nums) {
    sum += x;
    count += seen.getOrDefault(sum - k, 0);
    seen.merge(sum, 1, Integer::sum);
}

Python

seen = {0: 1}             # the empty prefix
total = count = 0
for x in nums:
    total += x
    count += seen.get(total - k, 0)
    seen[total] = seen.get(total, 0) + 1

The traps

  • Rebuilding per query: the answers are right, but each costs O(n). Build the prefix array once.
  • No padding at prefix[0]: ranges starting at 0 need special cases. Size it n + 1 with a leading 0.
  • Inclusive vs exclusive r: sums come out off by one. For inclusive r, use prefix[r + 1] - prefix[l].
  • No seed for the empty prefix: subarrays starting at index 0 are missed. Seed the map with {0: -1} or {0: 1}.
  • int prefix arrays in Java: large totals overflow. Use long[].

Staff-level points, one line each

  • Count map: 1,468 subarrays = the brute force; earliest-index map for the longest (latest gave 378, not 405).
  • Java -7 % 5 is -2; % counted 4 divisible subarrays, floorMod the correct 7.
  • Difference array: O(1) per range update, one prefix pass at the end.
  • 2D: P[r2+1][c2+1] - P[r1][c2+1] - P[r2+1][c1] + P[r1][c1].
  • Fenwick tree: about log2(n) steps per operation - the longest walk was 15 for 100,000 elements.
  • A Java int prefix of 100,000 x 30,000 was -1294967296.

Say it in an interview

  • "Any range sum is the difference of two prefixes."
  • "I pad with a zero so ranges starting at 0 need no special case."
  • "For subarrays summing to k I look up prefix - k in a map - that works with negatives."
  • "If the array changes between queries, I'd use a Fenwick tree."

Practice

This skill comes with 9 multiple-choice questions that tell you which misconception a wrong answer reveals and 2 graded problems. Your answers are graded and your mastery is tracked, so you'll know when the skill holds up. Running code and saving progress need a free account.

Practice Prefix Sums free

Range Sum Queries

MediumProCoding problemJava · Python

Given an array of integers nums and a list of range queries, each query (left, right) (0-indexed, inclusive), return the sum of nums[left..right] for every query.

The full statement, the examples and the hidden test suite are part of AI Proof Engineers Pro.

Largest Subarray with K Sum

MediumProCoding problemJava · Python

Given an array nums (which may contain negative numbers) and an integer k, return the length of the longest subarray whose elements sum to exactly k. Return 0 if no such subarray exists.

The full statement, the examples and the hidden test suite are part of AI Proof Engineers Pro.

Practice Prefix Sums free

No card needed. Lessons, practice questions and easy problems are free forever.

Free plan, no card · 7-day Pro trial · Cancel anytime