datarekha
Coding Patterns Medium Asked at AmazonAsked at GoogleAsked at Meta

Count the number of contiguous subarrays whose sum equals k.

The short answer

Build prefix sums on the fly and store their frequencies in a hash map. For each new prefix sum P, a subarray ending at the current index has sum k if some earlier prefix sum equalled P - k. Look that up in the map in O(1). One pass, O(n) time and space.

How to think about it

The hidden test here is whether you reach for a sliding window and get burned. The moment the array can hold negatives or zeros, a window breaks — growing or shrinking it no longer moves the sum in a predictable direction, so you cannot decide which way to slide. The answer the interviewer wants is prefix sums backed by a hash map, which handles any integers and counts exact sums in one pass.

The idea rests on a small rearrangement. Let the running prefix sum at the current index be prefix. A subarray ending here sums to k exactly when some earlier prefix sum equalled prefix - k, because the elements between that earlier point and now are the difference. So you keep a map from each prefix sum to how many times it has appeared, and at every step you ask: how many earlier prefixes equalled prefix - k? That count is the number of qualifying subarrays ending at this index, and you add it to the total. Seed the map with {0: 1} — one empty prefix exists before the array starts — then walk once, looking up prefix - k and recording prefix as you go.

A worked example

from collections import defaultdict

def subarray_sum(nums, k):
    count = defaultdict(int)
    count[0] = 1   # one empty prefix exists before index 0
    prefix = 0
    result = 0
    for num in nums:
        prefix += num
        result += count[prefix - k]   # earlier prefixes that complete a sum of k
        count[prefix] += 1
    return result

print(subarray_sum([1, 1, 1], 2))            # [1,1] at 0-1 and at 1-2
print(subarray_sum([1, 2, 3], 3))            # [1,2] and [3]
print(subarray_sum([-1, -1, 1], 0))          # negatives, k=0
print(subarray_sum([3, 4, 7, 2, -3, 1], 7))  # mixed signs
2
2
1
3

Walk the first call, [1, 1, 1] with k=2. The prefixes are 1, 2, 3. At prefix 2 you look for 2 - 2 = 0, find it once (the seed), and count one subarray; at prefix 3 you look for 3 - 2 = 1, find it once, and count a second. Total 2 — the windows [1,1] at indices 0-1 and 1-2. The last call returns 3, not the larger number a quick eyeball might guess: with mixed signs the only sums of 7 are [3,4], the lone [7], and [7,2,-3,1], so trusting the prefix map over intuition is the point.

Keep practising

All Coding Patterns questions

Explore further

Skip to content