0Count contiguous subarrays whose elements sum to k. A running prefix sum paired with a hash map of prefix-sum frequencies turns the count into a single linear pass — and it survives negative numbers, where a sliding window cannot.
Return how many contiguous subarrays of nums sum to k. With nums=[1,1,1], k=2 the answer is 2 — the windows [0,1] and [1,2] each sum to 2. With nums=[1,2,3], k=3 the answer is 2 ([1,2] and [3]).
P[i] be the sum of the first i elements. The subarray ending at the current index with sum k exists for every earlier prefix where P[j] = sum − k, because sum − P[j] = k. So keep a map of how many times each prefix sum has occurred; at each step add count[sum − k] to the answer. Seed it with {0:1} so subarrays starting at index 0 are counted.count = {0:1}, sum = 0, total = 0. The 0:1 entry represents the empty prefix so a window starting at index 0 is counted.x, do sum += x — the prefix sum up to here.count[sum − k] to total. This counts every earlier prefix that closes a sum-k window ending here.count[sum] += 1. Doing the lookup before the insert is what prevents an empty subarray (sum-0) from being miscounted.A two-pointer sliding window would be O(n) too, but it is simply wrong for arrays with negatives — there is no valid rule for when to advance the left pointer. The hash-map method trades O(n) space for correctness under negatives.
sum − k" trick powers Continuous Subarray Sum (store sum % k), Subarray Sums Divisible by K (store remainders), and Contiguous Array (map +1/−1 prefix to first index seen).{0:1} (the empty prefix has sum 0, seen once), sum = 0, total = 0. Target k = 2.1function subarraySum(nums: number[], k: number): number {2▶ const count = new Map<number, number>();3▶ count.set(0, 1); // empty prefix: sum 0 seen once4▶ let sum = 0; // running prefix sum5▶ let total = 0; // subarrays found67 for (const x of nums) {8 sum += x; // extend prefix by x9 total += count.get(sum - k) ?? 0; // prefixes that close a sum-k window10 count.set(sum, (count.get(sum) ?? 0) + 1);11 }12 return total;13}
00{0:1}function subarraySum(nums: number[], k: number): number {
const count = new Map<number, number>();
count.set(0, 1); // empty prefix: sum 0 seen once
let sum = 0; // running prefix sum
let total = 0; // subarrays found
for (const x of nums) {
sum += x; // extend prefix by x
total += count.get(sum - k) ?? 0; // prefixes that close a sum-k window
count.set(sum, (count.get(sum) ?? 0) + 1);
}
return total;
}{0:1}: a prefix sum of 0 has been seen once (the empty prefix). Without this seed, any subarray that starts at index 0 would be missed. sum and total start at zero.x makes sum the total of everything from index 0 up to the current element.sum - k marks the start of a subarray ending here that sums to k. We add the frequency of that prefix (not 1) because the same prefix sum can recur.count[sum] so future indices can close windows against it. Crucially this happens after the lookup, so the current prefix never matches itself as a zero-length window.total has accumulated one count for every qualifying subarray across the single pass.{0:1}?" It represents the empty prefix so subarrays beginning at index 0 (where sum === k) are counted.k === 0count the current element's prefix against itself as a zero-length window.((sum % k) + k) % k as the key instead of the raw sum.function subarraySum(nums: number[], k: number): number {
const count = new Map<number, number>();
count.set(0, 1); // empty prefix: sum 0 seen once
let sum = 0; // running prefix sum
let total = 0; // subarrays found
for (const x of nums) {
sum += x; // extend prefix by x
total += count.get(sum - k) ?? 0; // prefixes that close a sum-k window
count.set(sum, (count.get(sum) ?? 0) + 1);
}
return total;
}Fix a start index, extend the end, and keep a running inner sum, counting whenever it hits k. Correct and simple, but quadratic.
function subarraySum(nums: number[], k: number): number {
let total = 0;
for (let i = 0; i < nums.length; i++) {
let sum = 0;
for (let j = i; j < nums.length; j++) {
sum += nums[j];
if (sum === k) total++;
}
}
return total;
}sum - k.| count contiguous subarrays summing to k | prefix sum + freq map |
| array may contain negatives | prefix-sum map (NOT a window) |
| subarrays starting at index 0 | seed map with {0:1} |
| divisible-by-k / balanced 0s & 1s variant | store sum % k or +1/−1 prefix |
const count = new Map<number, number>();
count.set(0, 1); // seed the empty prefix
let sum = 0, total = 0;
for (const x of nums) {
sum += x;
total += count.get(sum - k) ?? 0;
count.set(sum, (count.get(sum) ?? 0) + 1);
}
return total;sum - k, since current sum - prefix = k.