Prefix Sum
Pre-compute cumulative sums so any range query is O(1). Pair with a hash map to count subarrays with a target sum in O(n) — works with negatives where sliding window fails.
Every subarray sum by brute force is O(n²). One pass to build prefix sums turns any range query into O(1). Add a hash map to count/find subarrays in O(n) — even with negative numbers.
So "does a subarray with sum k end at j?" ↔ "did we see prefix_sum − k before?"
Hash map stores frequencies of prefix sums seen → O(1) lookup per element
Two Modes of Prefix Sum
Mode 1: build the array for range queries. Mode 2: running sum + hash map for subarray search.
range_sum(l,r) = prefix[r+1] - prefix[l]result += count[sum-k]; count[sum] += 1The 3-Step Framework
Sentinel → formula → hash map seed.
Always start with prefix[0]=0. This sentinel makes the formula prefix[r+1]-prefix[l] work even when l=0, without any if-else branch. For the hash map approach, seed count={0:1} — the empty prefix has sum 0 and has been 'seen once', enabling subarrays that start from index 0.
# Array mode:
prefix = [0] * (n + 1)
for i in range(n):
prefix[i+1] = prefix[i] + nums[i]
# Hash map mode (seed first!):
count = defaultdict(int)
count[0] = 1 # empty prefix sentinel
prefix_sum = 0For 'count subarrays with sum k': you need prefix[j+1] - prefix[i] == k, i.e., prefix[i] == prefix[j+1] - k. So look up count[prefix_sum - k] BEFORE recording the current prefix_sum. Order matters — looking up after recording would count single-element subarrays twice.
for num in nums:
prefix_sum += num
# 1. LOOKUP first
result += count[prefix_sum - k]
# 2. STORE after lookup
count[prefix_sum] += 1Divisible by K: use remainder as the map key — two equal remainders mean divisible difference. Max length subarray with sum k: store FIRST occurrence of each prefix sum (don't overwrite). The length is i - first[prefix_sum - k], and you want the earliest i to maximise length.
# Divisible by K:
remainder = prefix_sum % k
result += count[remainder]
count[remainder] += 1
# Max length subarray sum = k:
if prefix_sum not in first:
first[prefix_sum] = i # don't overwrite!Pattern Recognition
'subarray sum', 'range query', 'divisible', 'equal left and right' → prefix sum.