Given an integer array nums and an integer k, return the total number of non-empty contiguous subarrays whose sum equals k.
Return 0 when no valid subarray exists or when nums is empty.
Example 1
Input: nums = [1, 1, 1], k = 2
Output: 2
Explanation: The subarrays [1, 1] starting at index 0 and 1 both sum to 2.
Example 2
Input: nums = [1, 2, 3], k = 3
Output: 2
Explanation: Subarrays [1, 2] and [3] sum to 3.
Brute Force Approach
The most direct idea is to generate every possible contiguous subarray and calculate the complete sum of each selected range.
Every pair of starting and ending indices defines one valid subarray. Checking all such ranges guarantees the correct count, but overlapping subarrays repeatedly add many of the same elements.
Algorithm
Store the array size in
n. Ifn == 0, return0because no non-empty subarray can be formed.Initialize
countwith0, where it stores the number of subarrays found whose sum is exactlyk.Treat every index
startas the beginning of a possible subarray and every indexendfromstartton - 1as its ending position.For each selected range
[start, end], initializecurrentSumwith0and add all elements fromstartthroughendto calculate that subarray's complete sum.If
currentSum == k, incrementcountbecause the selected range forms one valid subarray.Return
countafter every possible contiguous subarray has been examined.
Dry Run
Subarray Sum Equal K Brute Force Dry Run.png
Solution
#include <bits/stdc++.h>using namespace std;class Solution {public: long long subarraySum(vector<int>& nums, int k) { int n = nums.size(); if (n == 0) { return 0; } long long count = 0; /* * Generate every possible subarray * using its start and end indices. */ for (int start = 0; start < n; start++) { for (int end = start; end < n; end++) { long long currentSum = 0; // Calculate the sum of the selected range. for (int index = start; index <= end; index++) { currentSum += nums[index]; } // This range contributes when its sum equals k. if (currentSum == k) { count++; } } } return count; }};int main() { vector<int> nums = {1, 1, 1}; int k = 2; Solution solution; cout << solution.subarraySum(nums, k) << endl; return 0;}Complexity Analysis
Time Complexity: O(N³), where N represents the array size. Two loops select the starting and ending indices, while a third traversal calculates the sum of every selected range.
Space Complexity: O(1), because only loop indices, currentSum, and count require auxiliary storage.
Better Approach
The Brute Force Approach calculates every selected range sum from the beginning.
For a fixed starting index, the next subarray contains the previous range plus one additional ending element. Keeping a running sum removes the repeated range traversal and reduces the solution to two loops.
Algorithm
Store the array size in
n. If the array is empty, return0.Initialize
countwith0to keep track of how many subarrays have a sum equal tok.Treat every index
startas the beginning of a new group of subarrays and initializecurrentSumwith0for that starting position.Move
endfromstartton - 1and addnums[end]tocurrentSum. This extends the previous range by one element instead of recalculating its complete sum.Increment
countwhenevercurrentSum == k. Continue extending the range even if the sum becomes greater thank, because a later negative value may reduce it again.Return
countafter all starting and ending positions have been processed.
Dry Run
Subarray Sum Equal K Better Approach Dry Run.png
Solution
#include <bits/stdc++.h>using namespace std;class Solution {public: long long subarraySum(vector<int>& nums, int k) { int n = nums.size(); if (n == 0) { return 0; } long long count = 0; for (int start = 0; start < n; start++) { long long currentSum = 0; /* * Extend the current subarray one element * at a time and reuse its previous sum. */ for (int end = start; end < n; end++) { currentSum += nums[end]; // Count every range whose sum equals k. if (currentSum == k) { count++; } } } return count; }};int main() { vector<int> nums = {1, 1, 1}; int k = 2; Solution solution; cout << solution.subarraySum(nums, k) << endl; return 0;}Complexity Analysis
Time Complexity: O(N²), where N represents the array size. Every starting index extends through all possible ending positions, while each extension requires one addition.
Space Complexity: O(1), because only loop indices, currentSum, and count require auxiliary storage.
Optimal Approach
A prefix sum represents the total of all elements from the beginning of the array through the current index.
Suppose the current prefix sum is prefixSum. A subarray ending at the current index has sum k when an earlier prefix sum equals:
prefixSum - k
The same prefix sum may appear at multiple earlier positions. Every occurrence creates a different valid subarray, so the frequency of each prefix sum must be stored.
Algorithm
Create a hash map
prefixCountand store{0: 1}. This initial frequency represents the empty prefix before index0, allowing subarrays that begin at index0to be counted.Initialize
prefixSumwith0to store the running sum andcountwith0to store the total number of valid subarrays.Traverse the array from left to right and add the current element to
prefixSum.Calculate
neededSum = prefixSum - k. If this prefix sum occurred earlier, removing it from the current prefix leaves a subarray whose sum is exactlyk.Add the frequency of
neededSumtocount, since every earlier occurrence produces a different valid subarray ending at the current index. Then increase the frequency ofprefixSumfor future positions.Return
countafter the complete array has been processed. If the array is empty, the loop does not run and the result naturally remains0.
Dry Run
Subarray Sum Equal K Optimal Approach Dry Run.png
Solution
#include <bits/stdc++.h>using namespace std;class Solution {public: long long subarraySum(vector<int>& nums, int k) { unordered_map<long long, long long> prefixCount; /* * The empty prefix allows subarrays * starting from index 0 to be counted. */ prefixCount[0] = 1; long long prefixSum = 0; long long count = 0; for (int value : nums) { prefixSum += value; long long neededSum = prefixSum - k; /* * Every earlier occurrence of neededSum * forms a valid subarray ending here. */ if (prefixCount.find(neededSum) != prefixCount.end()) { count += prefixCount[neededSum]; } /* * Store the current prefix only after * checking earlier prefix sums. */ prefixCount[prefixSum]++; } return count; }};int main() { vector<int> nums = {1, 1, 1}; int k = 2; Solution solution; cout << solution.subarraySum(nums, k) << endl; return 0;}Complexity Analysis
Time Complexity: O(N) on average, where N represents the array size. Every element requires one hash-map lookup and one hash-map update.
Space Complexity: O(N), because the hash map may store up to N + 1 distinct prefix sums.
FAQs
Q1. Why are prefix-sum frequencies stored instead of only checking whether a prefix exists?
The same prefix sum may occur at multiple earlier positions. Every occurrence creates a different valid subarray ending at the current index.
Q2. Why is prefixCount initialized with {0: 1}?
The initial zero represents the empty prefix before the array begins. This allows a subarray starting at index 0 to be counted when its sum directly equals k.
Q3. Why is the current prefix sum stored after checking neededSum?
Only earlier prefix sums should create subarrays ending at the current index. Storing the current prefix first could incorrectly use the same position as both boundaries.
Q4. Why cannot the Better Approach stop when currentSum becomes greater than k?
Negative values may appear later and reduce the running sum. A sum greater than k can still become equal to k after further extension.
Q5. Can a sliding-window approach solve this problem?
A standard sliding window works reliably when all values are non-negative. Negative values make window expansion and contraction unpredictable, so prefix sums with a hash map are preferred.
Q6. How does the solution change when the longest subarray with sum k is required?
Store the earliest index of each prefix sum instead of its frequency. The distance between the current index and the earliest matching prefix determines the longest valid length.
Be the first to add a comment.