---
title: 'Prefix Sum'
description: 'Precomputed cumulative state for O(1) range queries.'
---
## The idea
Precompute running totals once. Then any range sum costs O(1).
Like mile markers on a highway.
Distance from mile 30 to mile 80? Subtract: 80 − 30 = 50.
You do not re-drive the road.
**The formula:** `sum(i..j) = prefix[j + 1] - prefix[i]`
## The picture
```mermaid
flowchart TD
A["nums: 3 1 4 1 5"] --> B["prefix: 0 3 4 8 9 14"]
B --> C["sum(1..3) = prefix[4] − prefix[1]
= 9 − 3 = 6"]
C --> D["Check: 1 + 4 + 1 = 6 ✓"]
style D fill:#2e7d32,color:#fff
```
The leading 0 matters. It makes ranges that start at index 0 work with no special case.
## Range Sum Query (LC 303)
Pay O(n) once at build time. Answer every query in O(1).
```python
from itertools import accumulate
class NumArray:
def __init__(self, nums: list[int]):
self.prefix = [0] + list(accumulate(nums))
def sum_range(self, left: int, right: int) -> int:
return self.prefix[right + 1] - self.prefix[left]
```
## Prefix + Hashmap (LC 560 — Subarray Sum Equals K)
The signature trick of this topic. The question flips:
"Which subarrays sum to k?" becomes
"At each point, how many *earlier* prefixes equal `current − k`?"
Because: if `prefix[j] − prefix[i] = k`, the slice between them sums to k.
```mermaid
flowchart LR
A["Walk the array,
carry running sum"] --> B["Ask the map:
seen sum − k before?"]
B --> C["Yes, m times →
add m to answer"]
B --> D["Record current sum
in the map"]
D --> A
style C fill:#2e7d32,color:#fff
```
```python
from collections import defaultdict
def subarray_sum(nums: list[int], k: int) -> int:
count = 0
current = 0
seen = defaultdict(int)
seen[0] = 1 # empty prefix — subarrays that start at 0
for n in nums:
current += n
count += seen[current - k] # ask first
seen[current] += 1 # record after
return count
```
**Order matters.** Ask before you record, or a subarray of length 0 counts itself when k = 0.
## Product variant (LC 238 — Product of Array Except Self)
Same idea, two directions. Prefix products from the left, suffix products from the right.
`answer[i] = left[i] × right[i]` — everything except i.
```python
def product_except_self(nums: list[int]) -> list[int]:
n = len(nums)
result = [1] * n
left = 1
for i in range(n):
result[i] = left
left *= nums[i]
right = 1
for i in range(n - 1, -1, -1):
result[i] *= right
right *= nums[i]
return result
```
## Complexity
| | Time | Space |
|---|---|---|
| Build | O(n) | O(n) |
| Each range query | O(1) | — |
| Prefix + hashmap | O(n) one pass | O(n) |
## Close-out ritual
Before you submit, say out loud:
1. Time and space complexity.
2. One edge case trace: range starting at 0, k = 0 with zeros in the array, or negative numbers (this is why sliding window fails and prefix + hashmap wins).
## Plan problems
**A-set:** LC 303 · 238 · 560
**B-set:** LC 525 · 974