Subarray Sum Equals K

medium

You're given an integer array nums and an integer k. Count how many subarrays of nums sum to exactly k, and return that count.

A subarray is a contiguous, non-empty block of the array — pick a start index and an end index and take everything between them, in order. Picking scattered elements doesn't count.

Note that nums may contain negative numbers and zeros, and valid subarrays may overlap — every distinct (start, end) pair whose sum is k counts once.

Hints

Every subarray is defined by a start and an end. Can you count them all directly — and what does that cost at n = 2 * 10^4?
The sum of nums[i..j] is runningTotal(j) - runningTotal(i-1) — a subarray sum is a difference of two prefix sums. What are you really searching for at each position?
Walking left to right, you need: how many earlier prefix sums equal prefix - k? A hash map from prefix sum → frequency answers that in O(1). Seed it with 0 → 1.

Common doubts

A sliding window relies on the sum growing when the window grows and shrinking when it shrinks. With negatives and zeros in nums, extending the window can decrease the sum, so the pointer-movement logic breaks. Sliding window works for the all-positive variant only.
A prefix sum of 0 exists before the array starts — the empty prefix. Without seeding seen[0] = 1, any subarray that starts at index 0 and sums to k would never be counted.
After. Look up seen[prefix - k] first, then record the current prefix. If you record first and k = 0, the current prefix matches itself and you incorrectly count an empty subarray at every step.
Negatives and zeros make the same prefix sum appear multiple times, and each earlier occurrence starts a distinct valid subarray ending at the current position. Longest-subarray variants keep only the earliest index; the counting variant needs the full frequency.

Interview follow-ups

Then prefix sums are strictly increasing and a two-pointer sliding window works in O(n) time and O(1) space — a strictly better trade-off the moment the negatives guarantee appears.
Same prefix-sum idea, different bookkeeping: store the earliest index of each prefix sum instead of its frequency, and maximize i - firstIndex[prefix - k] — that's the Longest Subarray with Sum K problem.
Yes: fix a pair of rows, collapse the columns between them into a 1-D array of column sums, and run this exact algorithm on it. Total O(rows^2 * cols) — the 1-D trick is the inner engine.
The one-pass structure already fits streaming — you only keep the running prefix and the map. The catch is memory: the map can grow to one entry per element, so for unbounded streams you'd discuss approximation or windowed variants.

Fun facts

  • The 0 → 1 seed is the same idea as a sentinel node in a linked list: invent an imaginary 'empty prefix' so the boundary case stops being special.
  • This exact map-of-prefix-sums pattern reappears in Subarray Sums Divisible by K, Contiguous Array, Binary Subarrays With Sum — and even Path Sum III, where the 'array' is a root-to-leaf path in a tree.

Asked at

AmazonGoogleMetaMicrosoftBloombergAdobe
Frequently Sometimes Occasionally
Example 1
Input: nums = [1,1,1], k = 2
Output: 2
Two subarrays sum to 2: [1,1] starting at index 0, and [1,1] starting at index 1.
Example 2
Input: nums = [1,2,3], k = 3
Output: 2
[1,2] and [3] both sum to 3.
Example 3
Input: nums = [1,-1,0], k = 0
Output: 3
[1,-1], [0], and [1,-1,0] all sum to 0 — negatives and zeros make extra answers possible.
Constraints

- 1 <= nums.length <= 2 * 10^4 - -1000 <= nums[i] <= 1000 - -10^7 <= k <= 10^7

Solve this problem →