Subarray Sum Equals K — The Best Explanation

Mdkamranr
8 min readJun 20, 2024

--

The “Subarray Sum Equals K” problem involves finding the total number of continuous subarrays in an array that sum up to a specific target value, K. This problem is related to subarray sum problems and has several applications in various fields. Here is a list of applications where the “Subarray Sum Equals K” problem or similar subarray sum problems can be useful:

Financial Analysis: In finance, this problem can be used to identify subarrays of daily stock prices that result in a specific profit or loss. It’s useful for analyzing trading strategies and portfolio management.

Data Analytics: Data analysts use subarray sum problems to find patterns or trends in datasets. This can help discover temporal correlations or anomalies within data.

Image Processing: In image processing, subarrays of pixel values can be analyzed to identify regions of interest, detect patterns, or perform various image recognition tasks.

Genomics and Bioinformatics: In genomics, this problem can help discover segments of a DNA sequence that exhibit specific traits or are associated with genetic disorders.

Database Query Optimization: In database systems, subarray sum problems can be used to optimize queries by finding contiguous data segments that meet certain conditions.

Network Traffic Analysis: In cybersecurity and network management, identifying subarrays of network traffic data with specific characteristics can help detect network anomalies or security threats.

Inventory Management: In retail and supply chain management, identifying subarrays of inventory data with certain characteristics can help in optimizing stock levels and demand forecasting.

These are just a few examples of the many applications where the “Subarray Sum Equals K” problem or related subarray sum problems can be valuable for data analysis, algorithm design, and problem-solving in various domains.

Brute-Force Approach :

Here’s the algorithm for the subarraySum function:

  1. Initialize variables len (length of the input nums array) and count (a counter to keep track of the subarrays whose sum is equal to k).
  2. Use two nested loops to consider all possible subarrays:
  • The outer loop runs from i equal to 0 to len — 1, representing the starting index of the subarray.
  • The inner loop, nested within the outer loop, runs from j equal to i to len — 1, representing the ending index of the subarray.

3. For each pair of i and j, calculate the sum of elements in the subarray:

  • Initialize a variable sum to 0 to keep track of the sum.
  • Use a third loop, which runs from s equal to i to j, to iterate over the elements in the subarray.
  • Add each element nums[s] to the sum to calculate the cumulative sum of elements in the subarray.

4. Check if the sum calculated in step 3 is equal to the target value k.

  • If sum is equal to k, increment the count to keep track of the subarrays that sum to k.

5. After all combinations of i and j have been considered, return the final value of count, which represents the total number of subarrays in the nums array whose sum is equal to k.

The given code uses a brute-force approach and has a time complexity of O(N³), which means it may not be efficient for large input arrays.

Brute-Force Code

class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
// Brute Force Solution Time O(N^3) & Auxiliary Space O(1)
// Time Limit Exceed(TLE) 61/89 test cases passed
int len = nums.size(), count = 0;
// Consider all possible subarrays
for (int i = 0; i < len; i++) {
for (int j = i; j < len; j++) { // Consider subarray from nums[i] to nums[j]
int sum = 0;
for (int s = i; s <= j; s++) { // Calculate sum of elements from nums[i] to nums[j]
sum += nums[s];
}
if (sum == k) // Check if sum is equal to k
count++;
}
}
return count;
}
};

Better solution Approach:

Here's the algorithm for the subarraySum function:

  1. Initialize variables len (length of the input nums array) and count (a counter to keep track of the subarrays whose sum is equal to k).
  2. Create a new array called ls (prefix sum array or left sum array) with an initial element of 0.
  • ls[i] will represent the sum of elements from nums[0] to nums[i].
  • Iterate through nums, and for each element, add the cumulative sum to ls and store it. This process builds the prefix sum array.

3. Use two nested loops to consider all possible subarrays:

  • The outer loop runs from i equal to 0 to ls.size() - 1, representing the starting index of the subarray.
  • The inner loop, nested within the outer loop, runs from j equal to i + 1 to ls.size() - 1, representing the ending index of the subarray.

4. For each pair of i and j, calculate the sum of elements in the subarray:

  • Check if the difference between ls[j] and ls[i] is equal to the target value k.
  • If ls[j] - ls[i] is equal to k, it means the sum of elements in the subarray from i to j is equal to k.
  • Increment the count to keep track of subarrays that sum to k.

5. After all combinations of i and j have been considered, return the final value of count, which represents the total number of subarrays in the nums array whose sum is equal to k.

The given code uses a more efficient approach by using a prefix sum array and has a time complexity of O(N^2), which is better than the brute-force approach, but it may still not be efficient for very large input arrays.

Better Solution Code

class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
// Better Solution Time O(N^2) & Auxiliary Space O(N)
// Time Limit Exceed(TLE) 84/89 test cases passed
int len = nums.size(), count = 0;
vector<int> ls; // prefix sum array or left sum array
// ls[i] will be sum of elements from nums[0] to nums[i]
ls.push_back(0);
for (int i = 0; i < len; i++)
ls.push_back(ls.back() + nums[i]); // inserting elements in ls

for (int i = 0; i < ls.size(); i++) {
for (int j = i + 1; j < ls.size(); j++) {
// For example: nums[]={2,8,5,-3,1,8}, k=10
// ls[]={2,10,15,12,13,21}, k=10
// nums[1]+nums[2]+nums[3]=8+5+(-3)=10.
// j runs from 1 to 3. For j=i+1 & j=1, we get i=0.
// Therefore i=0 & j=3.
// ls[j=3]-ls[i=0]=12-2=10 which is equal to k.
if (ls[j] - ls[i] == k)
count++;
}
}
return count;
}
};

Optimal solution Approach:

Here’s the algorithm for the subarraySum function:

  1. Initialize a variable ls (left sum or prefix sum) to 0. This variable will keep track of the cumulative sum of elements in the nums array as you traverse through it. It represents the sum of elements from the beginning of the array up to the current index.
  2. Get the length of the nums array and initialize a variable count to 0. This variable will keep track of the count of subarrays whose sum is equal to k.
  3. Create a map called m to keep track of the frequency of each value of ls. The map will store pairs of ls values and their corresponding frequencies. Initialize m[0] to 1. If k is 0, this is necessary to account for an empty subarray, which has a sum of 0. If k is non-zero, it ensures that if ls becomes equal to k at any point, it will be included in the count.
  4. Iterate through the nums array:
  • Update the ls by adding the current element nums[i] to it. This step accumulates the sum of elements from the beginning of the array up to the current index i.

5. For each i in the iteration:

  • Calculate x as ls — k, which represents the difference between the current ls value and the target value k.
  • Check if x has occurred as a value of ls before. If it has, it means there is a subarray whose sum is equal to k, and x is the corresponding ls value.
  • Increment the count by the frequency of x stored in the map m[ls — k]. This adds the count of subarrays with a sum of k for the current i.
  • Update the frequency of the current ls value in the map m.

6. After iterating through the entire nums array, return the final value of count, which represents the total number of subarrays whose sum is equal to k.

The given code uses a more efficient approach, with a time complexity of O(N), making it an optimal solution to find the count of subarrays with a sum equal to k.

Optimal Solution Code:

class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
// Optimal Solution Time O(N) & Auxiliary Space O(N)
int ls = 0; // ls is left sum variable or prefix sum variable
// whose value on nums[] traversal is the sum of nums[i] and
// all the elements that came before it (nums[i-1], nums[i-2], nums[i-3],.......nums[0])
int len = nums.size(), count = 0;
map<int, int> m; // m is a map that maps ls value to its frequency
// of occurrence as m[key, value] = {ls, frequency}
m[0] = 1; // If k=0, then subarray with no elements is also a subset of nums and sum of
// empty subarray elements is zero. So, number of subarrays with k(=0) sum has count
// of 1 initially. If k is non-zero, then ls-k=0 which means ls is equal to k.
// It means that for a certain index i in nums[i], the sum
// nums[0] + nums[1] + nums[2] ... + nums[i] is equal to k.
// m[0] = 1 is included in count if k=0 or ls-k=0.

for (int i = 0; i < len; i++) {
ls += nums[i];
/*
m[0] = 1


i | ls | m | m[ls-k] | count
---|------|------------|--------------|-------
0 | 1 | m[ 1] = 1 | m[ 1 - 8 ]=0 | 0
1 | 8 | m[ 8] = 1 | m[ 8 - 8 ]=1 | 1
2 | 14 | m[14] = 1 | m[14 - 8 ]=0 | 1
3 | 16 | m[16] = 1 | m[16 - 8 ]=1 | 2
4 | 19 | m[19] = 1 | m[19 - 8 ]=0 | 2
5 | 22 | m[22] = 1 | m[22 - 8 ]=1 | 3
6 | 24 | m[24] = 1 | m[24 - 8 ]=1 | 4

nums[] = [1, 7, 6, 2, 3, 3, 2 ]
i = 0, 1, 2, 3, 4, 5, 6
ls value = 1, 8, 14, 16, 19, 22, 24
x = ls - k k = 8
<----------><---------->
ls = 22
<---------------------->
*/
// If x = ls - k = 22 - 8 = 14 has been the value of ls anytime before, then it means that
// ls - x = 22 - 14 is k. Count will increment by number of times of x = ls - k occurrence which
// is stored in m[ls - k]
count += m[ls - k];
m[ls]++; // Store the frequency of ls value in map
}
return count;
}
};

--

--