Pattern

Prefix Sum

Precompute cumulative sums to answer range queries in O(1) time.

Roadmap

  1. What Is This Pattern?
  2. When to Use It
  3. Building the Prefix Sum
  4. Answering Range Queries
  5. Variant: Prefix Sum with HashMap
  6. Variant: 2D Prefix Sum
  7. Template Code
  8. Common Problems
  9. Interactive Demo
  10. Complexity Analysis
  11. Key Takeaways
Step 01

What Is This Pattern?

The prefix sum pattern transforms an array into a cumulative sum array, where each element stores the total of all elements from the beginning up to that index. Once built, any range sum query becomes a single subtraction instead of a loop.

The Core Idea

Build a prefix array where prefix[i] = sum of elements from index 0 to i. Then any range sum [l, r] = prefix[r] - prefix[l-1].

original
1
2
3
4
5
6
0 1 2 3 4 5
| | | | | |
prefix
1
3
6
10
15
21
0 1 2 3 4 5
sum(2..4) = prefix[4] - prefix[1] = 15 - 3 = 12
💡

Think of it like odometer readings. To find the distance between two points, you subtract the starting reading from the ending reading. Prefix sums work the same way: subtract the cumulative sum at the start from the cumulative sum at the end.

Step 02

When to Use It

Look for these signals in a problem:

Recognition Signals

Multiple range sum queries on a static array
If you need to answer many "sum from i to j" queries, brute force is O(n) per query. Prefix sums make each query O(1).
"Sum of subarray" problems
Any time the problem involves summing contiguous elements, prefix sums can often optimize the brute-force approach.
Finding subarrays with a given sum
"Count subarrays with sum = k" or "longest subarray with sum = k" often require the HashMap variant.
2D range queries
Sum of a submatrix can be computed in O(1) with a 2D prefix sum using inclusion-exclusion.
Step 03

Building the Prefix Sum

Each cell in the prefix array accumulates the running total. The formula is simple: prefix[i] = prefix[i-1] + nums[i]. Let's watch it build step by step from [1, 2, 3, 4, 5, 6].

Step-by-Step Construction

i = 0: prefix[0] = nums[0] = 1
nums
1
2
3
4
5
6
prefix
1
-
-
-
-
-
i = 1: prefix[1] = prefix[0] + nums[1] = 1 + 2 = 3
nums
1
2
3
4
5
6
prefix
1
3
-
-
-
-
i = 2: prefix[2] = prefix[1] + nums[2] = 3 + 3 = 6
nums
1
2
3
4
5
6
prefix
1
3
6
-
-
-
i = 3..5: continuing the pattern...
nums
1
2
3
4
5
6
prefix
1
3
6
10
15
21

Practical tip: Use a prefix array of size n + 1 with prefix[0] = 0. This eliminates the edge case when the range starts at index 0, since prefix[r+1] - prefix[l] always works without special checks.

Step 04

Answering Range Queries

Let's query the sum of elements from index 2 to 4 in our array [1, 2, 3, 4, 5, 6]. Using the size n+1 prefix array convention:

Query: sum(2, 4)

Using prefix[0] = 0 convention: rangeSum = prefix[r+1] - prefix[l]

nums
1
2
3
4
5
6
0 1 2 3 4 5
prefix
0
1
3
6
10
15
21
0 1 2 3 4 5 6
prefix[5] - prefix[2] = 15 - 3 = 12
prefix[r+1] - prefix[l] = prefix[4+1] - prefix[2] = 15 - 3 = 12

Verify: 3 + 4 + 5 = 12. No loop needed, just one subtraction.

Step 05

Variant: Prefix Sum with HashMap

For problems like "count subarrays with sum = k", we combine prefix sums with a HashMap. The key insight: if prefix[j] - prefix[i] = k, then the subarray from i+1 to j sums to k.

Why This Works

As we scan left to right computing the running sum, at each position j we ask: "Have I seen a prefix sum equal to currentSum - k before?" If yes, the subarray between that earlier position and j has sum exactly k.

The HashMap stores how many times each prefix sum has occurred, so we count all valid starting points in O(1).

Visual Walkthrough: nums = [1, 2, 3, -2, 5], k = 6

INDEX NUM SUM SUM-K IN MAP? COUNT
init - 0 - - 0
0 1 1 -5 no 0
1 2 3 -3 no 0
2 3 6 0 YES (1x) 1
3 -2 4 -2 no 1
4 5 9 3 YES (1x) 2

Found 2 subarrays with sum = 6: [1,2,3] and [3,-2,5].

HashMap Variant Template

// Subarray sum equals k (with HashMap)
Map<Integer, Integer> map = new HashMap<>();
map.put(0, 1);              // empty prefix has sum 0
int sum = 0, count = 0;

for (int num : nums) {
    sum += num;                // running prefix sum
    // How many earlier prefixes had sum = (sum - k)?
    count += map.getOrDefault(sum - k, 0);
    // Record this prefix sum
    map.merge(sum, 1, Integer::sum);
}
🎯

Why put(0, 1)? We initialize the map with sum 0 having count 1. This handles the case where a subarray starting from index 0 has sum exactly k. Without this, we would miss those subarrays.

Step 06

Variant: 2D Prefix Sum

For matrix problems, extend the pattern to two dimensions. Each cell prefix[i][j] stores the sum of the submatrix from (0,0) to (i,j).

Inclusion-Exclusion Formula

BUILD
prefix[i][j] =
  matrix[i][j]
  + prefix[i-1][j]
  + prefix[i][j-1]
  - prefix[i-1][j-1]
QUERY (r1,c1) to (r2,c2)
sum =
  prefix[r2][c2]
  - prefix[r1-1][c2]
  - prefix[r2][c1-1]
  + prefix[r1-1][c1-1]

The red term corrects for the double subtraction of the overlapping rectangle. This is the classic inclusion-exclusion principle.

Step 07

Template Code

Here is the complete annotated template covering both the basic prefix sum and the HashMap variant.

Basic Prefix Sum + Range Query

// Build prefix sum (size n+1, prefix[0] = 0 for cleaner math)
int[] prefix = new int[n + 1];
for (int i = 0; i < n; i++) {
    prefix[i + 1] = prefix[i] + nums[i];
}

// Range sum query [l, r] inclusive  —  O(1)
int rangeSum = prefix[r + 1] - prefix[l];

Subarray Sum Equals K (HashMap Variant)

Map<Integer, Integer> map = new HashMap<>();
map.put(0, 1);                  // base case: empty prefix
int sum = 0, count = 0;

for (int num : nums) {
    sum += num;                    // running prefix sum
    count += map.getOrDefault(sum - k, 0);
    map.merge(sum, 1, Integer::sum);
}
return count;
Step 08

Common Problems

Practice these problems in order, from the basic range query to more creative applications:

#303 Range Sum Query - Immutable Easy
#304 Range Sum Query 2D - Immutable Medium
#560 Subarray Sum Equals K Medium
#238 Product of Array Except Self Medium
#525 Contiguous Array Medium
📝

#525 Contiguous Array is a clever twist: treat 0 as -1, then "equal number of 0s and 1s" becomes "subarray sum = 0." This transforms a counting problem into a prefix sum + HashMap problem.

Step 09

Interactive Demo

Enter an array, build the prefix sum step by step, then query any range instantly.

⚙ Prefix Sum Visualizer


Step 10

Complexity Analysis

Build
O(n)
Query
O(1)
Space
O(n)

Building the prefix array requires a single pass through the input. After that, each range query is a constant-time subtraction. The trade-off is O(n) extra space for the prefix array.

Comparison with Brute Force

APPROACH BUILD PER QUERY Q QUERIES
Brute Force - O(n) O(n * Q)
Prefix Sum O(n) O(1) O(n + Q)

When Q queries is large (say Q = 100,000 on an array of n = 100,000), brute force does 10 billion operations while prefix sum does just 200,000. That is the difference between TLE and accepted.

Step 11

Key Takeaways

  • 1 Prefix sum trades space for speed. Pay O(n) space once, get O(1) range queries forever.
  • 2 Use size n+1 with prefix[0] = 0. This eliminates boundary checks and makes the formula prefix[r+1] - prefix[l] work universally.
  • 3 HashMap variant unlocks "sum equals k" problems. Store prefix sums as you go and look up currentSum - k for O(n) total time.
  • 4 Always initialize the map with {0: 1}. Forgetting this is the most common bug. It handles subarrays that start at index 0.
  • 5 Extends to 2D. The same idea works for matrices via inclusion-exclusion, enabling O(1) submatrix sum queries.
  • 6 Look for creative transformations. Problems like #525 (Contiguous Array) and #238 (Product Except Self) use prefix logic with a twist. The pattern is more versatile than it first appears.