readyforhires

Prefix Sum 101

Fundamental · 4 chapters · 8 min read · Precompute running totals once and answer any range-sum question instantly.

Practise this in the app All guides

What prefix sums are

The idea

A prefix sum array stores, at position i, the total of all elements before it. With pre[0] = 0 and pre[i + 1] = pre[i] + a[i], the sum of any range a[l..r] is simply pre[r + 1] - pre[l]. You pay O(n) once to build it and then answer each range-sum query in O(1).

The deeper insight is that a subarray sum is the difference of two prefix sums. That turns questions about subarrays into questions about pairs of prefix values, and pairs can be found quickly with a hash map. This is what makes prefix sums powerful in interviews, far beyond simple range queries.

Signals in a problem statement

Mental model

Picture a running balance in a bank passbook. The amount spent between two dates is the balance on the first date minus the balance on the second. You never need to add up the individual transactions again. Similarly, if two moments have the same balance, nothing net was added between them: that is exactly the "subarray with sum 0" condition.

Core patterns with templates

1. Build and query

def build_prefix(a):
    pre = [0] * (len(a) + 1)
    for i, x in enumerate(a):
        pre[i + 1] = pre[i] + x
    return pre

def range_sum(pre, l, r):
    return pre[r + 1] - pre[l]

Python's itertools.accumulate(a, initial=0) builds the same list in one line.

2. Pivot index (left sum equals right sum)

def pivot_index(a):
    total, left = sum(a), 0
    for i, x in enumerate(a):
        if left == total - left - x:
            return i
        left += x
    return -1

3. Count subarrays with sum k (prefix sum + hash map)

from collections import defaultdict

def subarray_sum(a, k):
    count = defaultdict(int)
    count[0] = 1
    run = ans = 0
    for x in a:
        run += x
        ans += count[run - k]
        count[run] += 1
    return ans

Seeding count[0] = 1 handles subarrays that start at index 0. Example: a = [1, 2, 3], k = 3. Running sums are 1, 3, 6. At 3 we find count[0] = 1 (subarray [1,2]); at 6 we find count[3] = 1 (subarray [3]). Answer 2.

4. Longest subarray with sum 0 (first occurrence)

def longest_balanced(bits):
    first = {0: -1}
    run = best = 0
    for i, b in enumerate(bits):
        run += 1 if b == 1 else -1
        if run in first:
            best = max(best, i - first[run])
        else:
            first[run] = i
    return best

For counting store how many times each sum appeared; for longest store the first index only.

Complexity, mistakes and edge cases

Complexity

TaskTimeSpace
Build prefix arrayO(n)O(n)
One range queryO(1)
Count subarrays with sum kO(n)O(n) map
2D prefix buildO(rows × cols)O(rows × cols)

Common mistakes

Edge cases

Empty array, single element, all zeros (many overlapping answers), k = 0, very large or very negative values, and a pivot at index 0 or at the last index (the empty side sums to 0).

2D prefix sums in one formula

P[i+1][j+1] = grid[i][j] + P[i][j+1] + P[i+1][j] - P[i][j]. The sum of the rectangle from (r1, c1) to (r2, c2) is P[r2+1][c2+1] - P[r1][c2+1] - P[r2+1][c1] + P[r1][c1]. Draw the four rectangles once and you will never forget it.

Variations and practise

How interviewers twist it

How to explain it

Say: "A subarray sum is pre[j] - pre[i], so I need the number of earlier prefix values equal to pre[j] - k, which I keep in a hash map." That one sentence shows you understand the idea rather than a memorised template.

Practise

The problems below cover the pivot index, counting subarrays with a target sum (with negatives allowed), and the longest balanced subarray. For each one, write the first few running sums on paper before coding.

Practise

Easy

Medium

Hard

Practise this in the app All guides