Subarray Sum Equals K

medium LeetCode #560
array hash-table prefix-sum

Description

Given an array of integers nums and an integer k, return the total number of subarrays whose sum equals to k.

A subarray is a contiguous non-empty sequence of elements within an array.

Example 1:
Input: nums = [1, 1, 1], k = 2
Output: 2
Explanation: There are two subarrays that sum to 2: [1, 1] (indices 0-1) and [1, 1] (indices 1-2).

Example 2:
Input: nums = [1, 2, 3], k = 3
Output: 2
Explanation: There are two subarrays that sum to 3: [1, 2] (indices 0-1) and [3] (index 2).

Example 3:
Input: nums = [1, -1, 0], k = 0
Output: 3
Explanation: Three subarrays sum to 0: [1, -1] (indices 0-1), [0] (index 2), and [1, -1, 0] (indices 0-2).

Constraints

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

Complexity

Show Complexity
  • Time: O(n)
  • Space: O(n)

Hints

Show Hints
Pattern
Prefix sum with hash map
Approach
For each prefix sum, check how many times (prefix_sum - k) has occurred. If prefix_sum - k exists, those positions form valid subarrays ending at current index.
Complexity
Use hash map to store prefix sum frequencies, lookup in O(1)

Notes

Show Notes

Subarray Sum Equals K

Problem

Given an array of integers nums and an integer k, return the total number of subarrays whose sum equals to k.

Key Insight

If we have a prefix sum at index j and another prefix sum at index i (where i < j), then:

sum of subarray [i+1, j] = prefix[j] - prefix[i]

So if prefix[j] - prefix[i] = k, then we found a valid subarray!

Rearranging: prefix[i] = prefix[j] - k

This means: At each position j, we ask “how many previous prefix sums equal curr - k?”

Approach

  1. Iterate through the array, keeping a running prefix sum (curr)
  2. At each position, check if curr - k exists in the cache
  3. If it exists, the frequency tells us how many subarrays ending at the current position sum to k
  4. Add the current prefix sum to the cache

The cache stores “how many times have we seen this prefix sum before?” — and that count directly translates to the number of valid subarrays.

Walkthrough

Let’s trace through nums = [1, 1, 1], k = 2:

nums:      [1, 1, 1]
indices:    0  1  2

prefix sums:
  prefix[0] = 1
  prefix[1] = 2
  prefix[2] = 3

Initialize: m = {0: 1}, curr = 0, count = 0

The map stores: {prefix_sum: how many times we've seen it}
We start with {0: 1} to represent the empty prefix (before index 0).

Index 0: nums[0] = 1

curr = 0 + 1 = 1
Looking for: curr - k = 1 - 2 = -1
Is -1 in map? NO
count stays 0

Add curr to map: m = {0: 1, 1: 1}

Index 1: nums[1] = 1

curr = 1 + 1 = 2
Looking for: curr - k = 2 - 2 = 0
Is 0 in map? YES, with frequency 1
count = 0 + 1 = 1

Why? We found a prefix sum of 0 (the empty prefix before the array).
  sum[0..1] = prefix[1] - 0 = 2 - 0 = 2 = k
  Subarray found: [1, 1] (indices 0-1)

Add curr to map: m = {0: 1, 1: 1, 2: 1}

Index 2: nums[2] = 1

curr = 2 + 1 = 3
Looking for: curr - k = 3 - 2 = 1
Is 1 in map? YES, with frequency 1
count = 1 + 1 = 2

Why? We found prefix[0] = 1.
  sum[1..2] = prefix[2] - prefix[0] = 3 - 1 = 2 = k
  Subarray found: [1, 1] (indices 1-2)

Add curr to map: m = {0: 1, 1: 1, 2: 1, 3: 1}

Result: count = 2

Why Frequency Matters

Let’s trace nums = [0, 0, 0], k = 0:

Initialize: m = {0: 1}, curr = 0, count = 0

Index 0: nums[0] = 0

curr = 0 + 0 = 0
Looking for: curr - k = 0 - 0 = 0
Is 0 in map? YES, freq = 1
count = 0 + 1 = 1   -> found [0] (indices 0-0)

Update map: m = {0: 2}  (now we've seen prefix sum 0 twice)

Index 1: nums[1] = 0

curr = 0 + 0 = 0
Looking for: 0 - 0 = 0
Is 0 in map? YES, freq = 2
count = 1 + 2 = 3   -> found [0] (index 1), and [0, 0] (indices 0-1)

Update map: m = {0: 3}

Index 2: nums[2] = 0

curr = 0 + 0 = 0
Looking for: 0 - 0 = 0
Is 0 in map? YES, freq = 3
count = 3 + 3 = 6   -> found [0] (index 2), [0, 0] (indices 1-2), [0, 0, 0] (indices 0-2)

Update map: m = {0: 4}

Result: count = 6

Solution

def solution(nums: list[int], k: int) -> int:
    m = {0: 1}      # empty prefix has sum 0, seen once
    curr = 0        # running prefix sum
    count = 0

    for num in nums:
        curr += num

        # How many previous prefixes give us a valid subarray?
        if curr - k in m:
            count += m[curr - k]

        # Record this prefix sum
        m[curr] = m.get(curr, 0) + 1

    return count

Complexity

  • Time: O(n) - single pass through the array
  • Space: O(n) - hash map can store up to n distinct prefix sums

Solutions

Show PY Solution
def solution(nums: list[int], k: int) -> int:
    m = {0: 1}
    curr = 0
    count = 0

    for right in range(len(nums)):
        curr += nums[right]
        if curr - k in m:
            count += m[curr - k]
        if curr not in m:
            m[curr] = 0
        m[curr] += 1

    return count