Example 1
ready- Input
nums = [ 1, 1, 1 ] k = 2- Expected
2- Why
- the first two and last two values each total 2
A week of gains and losses can swing in both directions yet still finish exactly on a target. The matching stretch might begin anywhere, and more than one stretch can land on the same total.
Given an integer array nums and an integer k, return how many contiguous
subarrays — non-empty slices whose elements sit next to one another — add up to exactly
k.
A few ground rules:
k and later
come back, so "too large" isn't a safe reason to stop.1 <= nums.length <= 100_000-1_000 <= nums[i] <= 1_000-10_000_000 <= k <= 10_000_000Hints
Fix a starting index, grow the slice one value at a time, and keep its sum. That avoids re-adding the whole slice, but how many start/end pairs remain?
If the running total through the current position is sum, a slice ending here
totals k when an earlier running total was exactly sum - k.
The same earlier total may occur several times, and each occurrence gives a
different slice. Store running total → number of times seen, beginning with
0 → 1 for the position before the array starts.
Could you process the numbers as a stream, counting every new matching slice without storing the original array?
Visible cases
nums = [
1,
1,
1
]
k = 22nums = [
1,
2,
3
]
k = 32nums = [
1,
-1,
0
]
k = 03Interview signal
Choose each possible starting position. From there, extend the ending position one step
at a time and carry the current sum forward. Every time that sum equals k, you've
found one more slice.
def subarray_sum(nums: list[int], k: int) -> int:
total = 0
for start in range(len(nums)):
current = 0
for end in range(start, len(nums)):
current += nums[end]
if current == k:
total += 1
return totalTime O(n²) — there are about n²/2 start/end pairs. Space O(1).
Negative values are why you can't stop when current passes k: a later negative
number can pull it back down.
A prefix sum is the total from the beginning of the array through one position.
Suppose the current prefix sum is running. A slice ending here sums to k exactly
when an earlier prefix sum equals running - k:
running - earlier = k
So you don't need the earlier positions themselves. You need a frequency map that tells you how many times each earlier prefix sum occurred. Add that frequency to the answer, then record the current sum for future positions.
def subarray_sum(nums: list[int], k: int) -> int:
frequencies: dict[int, int] = {0: 1}
running = 0
total = 0
for value in nums:
running += value
total += frequencies.get(running - k, 0)
frequencies[running] = frequencies.get(running, 0) + 1
return totalThe initial 0: 1 represents the empty prefix before index 0. Without it, you'd miss
every matching slice that begins at the first element. Looking up before recording also
keeps that empty prefix separate from the current position.
Repeated prefix sums aren't noise — they're separate starting boundaries. If
running - k has appeared three times, the current endpoint completes three different
valid slices.
Time O(n) — one pass with O(1) expected map work per value. Space O(n) for the prefix-sum frequencies.
Ready to run.
3 cases are queued.
Visible testcase
Case 1
Expected
2