intermediate6 min read·Updated September 17, 2026

Subarray Sum Equals K Explained: Counting [1, -1, 1]

Master Subarray sum equals K (prefix sums) explained via [1, -1, 1]. Build a prefix sum mental model, trace every step, and handle negative numbers.

By Learnisim AI·Published September 17, 2026
LEARNING ARCSetup → Model in the example → Full trace → Twist → Edge cases → Apply
PREREQUISITES
  • basic arrays
  • hash maps
  • cumulative sums
Subarray Sum Equals K: Prefix Sums & Hash Map (nums = [1, -1, 1], k = 1) 1. Array & Brute Force Challenge 1 idx 0 -1 idx 1 1 idx 2 Brute Force O(n² or n³): Re-adds every slice from scratch 2. The Prefix Sum Mental Model SubarraySum(i, j) = P[j] - P[i-1] Transforms range-sum into point-lookup frequency! Target P - k 3. Step-by-Step Algorithm Trace (k = 1, init: map = {0: 1}, count = 0) Step 1: nums[0] = 1 • Update P: 0 + 1 = 1 • Target needed (P - k): 1 - 1 = 0 • Check map for 0: Found (freq 1) • Add 1 to count → count = 1 • Record P=1 in map: {0:1, 1:1} Step 2: nums[1] = -1 • Update P: 1 + (-1) = 0 • Target needed (P - k): 0 - 1 = -1 • Check map for -1: Not found (0) • Count unchanged → count = 1 • Record P=0 in map: {0:2, 1:1} Step 3: nums[2] = 1 • Update P: 0 + 1 = 1 • Target needed (P - k): 1 - 1 = 0 • Check map for 0: Found (freq 2) • Add 2 to count → count = 3 • Record P=1 in map: {0:2, 1:2} Final Result: Total Contiguous Subarrays Summing to K (1) is exactly 3 O(n) Time!
How many subarrays of [1, -1, 1] sum to 1 overview diagram
Why

Why Brute Force Fails: Counting Contiguous Subarrays

Imagine you are handed the array and asked to find how many contiguous subarrays sum up to . A contiguous subarray is any unbroken slice of the array, such as index 0 to 0, or index 0 to 2. Without any clever techniques, your first instinct might be to write two nested loops to check every possible starting point and ending point. For an array of size , this brute-force approach requires evaluating roughly slices, and if you recalculate sums from scratch each time, you might even hit time complexity. As arrays grow from three elements to thirty thousand elements, checking every single window becomes computationally impossible. We need a way to look at running totals so we don't have to keep re-adding past elements.
Why Brute Force Fails: Counting Contiguous Subarrays (k = 1) Target Array: nums = [1, -1, 1], k = 1 idx 0 1 idx 1 -1 idx 2 1 6 possible subarrays Brute Force Exploration: Two Nested Loops Evaluating Every Window O(N²) Start i=0 [0..0] sum = 1 (✓) k=1 [0..1] sum = 0 (✗) [0..2] sum = 1 (✓) k=1 Start i=1 [1..1] sum = -1 (✗) [1..2] sum = 0 (✗) Start i=2 [2..2] sum = 1 (✓) k=1 Scaling Bottleneck: For N = 30,000 elements, nested loops require ~450,000,000 checks (O(N²) or O(N³)). Time limit exceeded! The Prefix Sum Breakthrough (O(N)) Instead of recalculating overlapping slices, use running sums & hash map frequency tracking: Total Valid Subarrays Found = 3
Why Brute Force Fails: Counting Contiguous Subarrays diagram
Model

The Prefix Sum Mental Model: Turning Ranges into Points

Instead of recalculating the sum of every contiguous slice from scratch, we define a running total called the prefix sum, denoted , which accumulates all elements from index 0 up to index . For our locked working example of , the prefix sums as we walk through the array are 1, then 0, and finally 1. Notice how the sum of any subarray from index to is simply the difference between two prefix sums: . We are no longer looking at nested index loops; we are looking at running totals and asking how often a required past prefix sum has appeared. This transforms a range-sum problem into a point-lookup frequency problem.
The Prefix Sum Mental Model: Turning Ranges into Points Example: nums = [1, -1, 1], Target K = 1 | SubarraySum(i, j) = P_j - P_{i-1} 1. Naive Range Sums (Nested Loops) 1 idx 0 -1 idx 1 1 idx 2 Check all i..j slices O(N²) redundant recalculations! 2. Running Prefix Sums (P_i) P₀=0 (base) P₁=1 (1) P₂=0 (1-1) P₃=1 (0+1) Accumulates elements from index 0 to i 3. The Equation: SubarraySum(i, j) = K ⟹ P_j - K = P_{i-1} Instead of searching ranges, at each step j we ask: “How many times has P_j - K appeared in our past prefix sums?” At P_3 = 1, we need P_3 - 1 = 0 Past 0s seen: P₀ (0) and P₂ (0) ⟹ 2 matches! 4. Running Hash Map Frequency Counter (O(N) Total Time) { 0 : 2 } Count = 2 valid subarrays summing to 1! Result: 2 Subarrays
The Prefix Sum Mental Model: Turning Ranges into Points diagram
Worked example

Tracing the Prefix Sum Algorithm Step by Step

Now that we have the prefix sum mental model, let's execute the algorithm on our locked example: and . Instead of checking every starting index, we maintain a running prefix sum and a hash map frequency table that tracks how many times each prefix sum has appeared so far. We initialize the map with to handle any subarray that starts directly from index 0.
Given: , , , , .
Step 1: Process element .
- Update .
- Calculate the target we need to find in our map: .
- Check map for 0: it exists with frequency 1. Add 1 to . .
- Record current in map. .
Step 2: Process element .
- Update .
- Calculate target: .
- Check map for : frequency is 0. remains 1.
- Record current in map. .
Step 3: Process element .
- Update .
- Calculate target: .
- Check map for 0: frequency is 2. Add 2 to . .
- Record current in map. .
Result: The total count of subarrays summing to 1 is 3, matching our expected result.
Prefix Sum Algorithm Trace: nums = [1, -1, 1], k = 1 Array Elements: 1 i = 0 -1 i = 1 1 i = 2 Running State Summary: Final Count = 3 | Target k = 1 Step 1: nums[0] = 1 • Update P: 0 + 1 = 1 • Target P - k: 1 - 1 = 0 • Map lookup '0': found (freq 1) • Add 1 to count (count = 1) • Record P=1 in map Hash Map State: {0: 1, 1: 1} Count = 1 Step 2: nums[1] = -1 • Update P: 1 + (-1) = 0 • Target P - k: 0 - 1 = -1 • Map lookup '-1': freq 0 • Count unchanged (count = 1) • Record P=0 in map Hash Map State: {0: 2, 1: 1} Count = 1 Step 3: nums[2] = 1 • Update P: 0 + 1 = 1 • Target P - k: 1 - 1 = 0 • Map lookup '0': found (freq 2) • Add 2 to count (count = 3) • Record P=1 in map Hash Map State: {0: 2, 1: 2} Final Count = 3 Initial state started with {0: 1}. Each step tracks running prefix sum P and adds map frequency of (P - k) to count.
Tracing the Prefix Sum Algorithm Step by Step diagram
Practice

Practice

You have seen how the prefix sum frequency map tracks past values to instantly find valid subarrays for and . Now, test your understanding on a slightly altered array to see if you can trace the state transitions yourself. Consider and . Imagine stepping through each index while updating your running prefix sum and checking the frequency map for . Think about how the zero in the middle alters the running prefix sum without changing the target count.
Apply

Transfer: Adapting Prefix Sums for New Signatures

We began with the combinatorial challenge of counting subarrays in our working example nums = [1, -1, 1] with , moving from checks to an single-pass frequency map. The true power of this mental model lies in its invariance to domain shifts. When a problem asks for continuous segments matching a target sum, the prefix sum equation remains our bedrock regardless of whether the array contains negative numbers, zeros, or streams of identical digits. By maintaining the running prefix sum and checking our frequency hash map, we transform range-query problems into point-lookup problems.

FAQ

How many subarrays sum to 1 in the example [1, -1, 1]?
There are 3 valid subarrays that sum to 1: [1] (index 0), [1, -1, 1] (indices 0 to 2), and [1] (index 2).
Why does the brute force approach fail for subarray sum problems?
Checking every possible start and end index takes O(n²) or O(n³) time, which TLEs for large arrays. Prefix sums with a hash map reduce this to O(n).
Can prefix sums handle negative numbers in the array?
Yes. Unlike sliding window (which requires positive numbers for monotonic expansion), prefix sums with a hash map safely handle negative numbers and zeros.
What is the time and space complexity of the optimal prefix sum approach?
Both time and space complexity are O(n), where n is the number of elements in the array, due to a single pass and storing prefix frequencies in a hash map.

Keep learning