``
Problem
Given an array of integers nums
and an integer k
, return the total number of subarrays whose sum equals to k
.
Examples
Example 1:
Input: nums = [1,1,1], k = 2
Output: 2
Example 2:
Input: nums = [1,2,3], k = 3
Output: 2
Solution
Let’s take an example not given in the question by taking negative numbers
Input: nums[]=[-1, -1, 1] && k = 0
Output: 1
So, the answer should be ‘1’ as their is only one subarray whose sum is 0 i.e (-1 + 1)
Method 1 - Brute Force
- Since we are very obedient person and don’t want to do anything extra from our side.
- So, we will try to generate the sum of each subarray and if matches with
k
, then increment our answer. - Like, this is the most basic thing we can do.
public int subarraySum(int[] nums, int k) {
int n = nums.length;
int ans = 0;
for (int i = 0; i < nums.length; i++) {
int sum = arr[i];
// if element itself equal to k, then also increment count
if(sum == k) {
ans++;
}
for (int j = 0; j < n; i++) {
sum += arr[j]; // add elements with sum
// if at any point they become equal to k
if(sum == k) {
ans++;
}
}
return ans;
}
}
Complexity
- ⏰ Time complexity:
O(n^2)
- 🧺 Space complexity:
O(1)
Method 2 - Using Prefix Sum but Still Naive
- Calculate the prefix sum of the array.
- Now loop over the array in a nested way,
prefix[j] - prefix[i]
is equal tok
. Increment our count: For eg. consider the array[1, 2, 3, 4, 5]
andk=9
, we have below prefix sum.
index : 0, 1, 2, 3, 4
arr[]: [1, 2, 3, 4, 5]
prefix[]:[1, 3, 6, 10, 15]
↑ ↑
We see index 0
and index 3
has difference of k
. Likewise index 2
and index 4
have difference k
. That is our answer:
Code
Java
public int subarraySum(int[] nums, int k) {
int ans = 0;
int[] prefix = new int[nums.length];
prefix[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
prefix[i] = prefix[i-1] + nums[i];
}
if(nums[0] == k){
ans++;
}
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < i; j++){
if(prefix[i] - prefix[j] == k){
ans++;
}
}
return ans;
}
}
Complexity
- ⏰ Time complexity:
O(n^2)
- 🧺 Space complexity:
O(n)
So, now we use map.
Method 3 - Using Prefix Sum with Map
- Instead of traversing the whole array every time, can we able to store prefix sum already and then check with that.
- So, with the help of an
unordered map
, we will store sum.
Intuition Before Code
So, suppose we have an array as arr[]: [1,2,3,4,5]
and k = 9
Our answer will be ‘2’ i.e (2 + 3 + 4 and 4 + 5)
Now, if we store our prefix sum array then it should looks like:
index : 0, 1, 2, 3, 4
arr[]: [1, 2, 3, 4, 5]
prefix[]:[1, 3, 6, 10, 15]
↑ ↑
How, we will find our subarray (2 + 3 + 4) using prefix sum, see:
- Look at prefix sum array. Index 0 and 3. Prefix sum at index
0
is1
and index3
is10
. - Now question - How much prefix sum increased from index
0
to3
? Ans - Difference between 2 sums at index0
and3
, i.e. (10-1) = 9. - If (
10 - 1
) sum increases from index0
to3
, then we can say that, ok, this difference, should be the sum of elements greater than index 0, and upto index 3, i.e from index 1 to index 3,right. - Now, if we will see then we find out (
10 - 1
) is nothing but our ‘k’ that is 9. - Why use map? So, we find out, that a subarray may also exist if this particular condition satisified, i.e
(prefix[i] - k) should exist in our map,
How? see,
If
prefix[i] - prefix[j] = k
wherei > j
(i, j any index, in our case they are i = 3, j = 0)prefix[i] - k = prefix[j]
, (simple maths) i.e if we are able to find (prefix[i] - k) is exist in our map, i.e prefix[j] so, we can say that from index j + 1 to i, the sum of the elements is k, right na, hence it proves that their exist an subarray from index j + 1 to i whose sum is k.
Now, for subarray (4 + 5) we again find this valid see -
index : 0, 1, 2, 3, 4
arr[]: [1, 2, 3, 4, 5]
prefix[]:[1, 3, 6, 10, 15]
↑ ↑
if we see our prefix sum at
index 4
then it is15
and also prefix sum atindex 2
is6
. So, we can say that from index 2 to 4 our prefix sum increases from 6 to 15, right,So on putting a question, HOW MUCH ? means how much our sum increase from index 2 to index 4. Answer is
15-6=9
, which is equal tok
.So, we find out, that a subarray may also exist if this particular condition satisified, i.e (
prefix[i] - k
) should exist in our map, right na,How? see,
If
prefix[i] - prefix[j] = k
where i > j (i, j any index, in our case they are i = 4, j = 2)prefix[i] - k = prefix[j]
na, (simple maths)i.e if we are able to find (
prefix[i] - k
) is exist in our map, i.eprefix[j]
so, we can say that from index j + 1 to i, the sum of the elements is k, right na, hence it proves that their exist an subarray from index j + 1 to i whose sum is k.I hope u got the reason now, why we will do (
prefix[i] - k
) in our code.
In the code below, we are not using prefix array
, but sum
variable, which stores current prefix value. And then we are saving it in the hashmap, instead of array.
Code
Java
public int subarraySum(int[] nums, int k) {
int count =0;
HashMap<Integer, Integer> map = new HashMap<>();
map.put(0,1);
int sum =0;
for( int a: nums ){
sum += a;
if(map.containsKey(sum- k) ){
count += map.get(sum- k);
}
map.put(sum, map.getOrDefault(sum,0) + 1);
}
return count;
}
Complexity
- ⏰ Time complexity:
O(n)
- 🧺 Space complexity:
O(n)