Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Continuous Subarray sum #113

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions Dynamic-Programming/ContinuousSubarraySum/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
## Continous Subarray Sum

<p>
<img align="center" width="800px" alt="Question Screenshot" src="./../../Images/ContinuousSubarraySum/question.png">
</p>

---

### Motivation
We are given an array of Integers `nums` and `K`. we have to find a continuous subset of the array of `length>=2` whose sum is of the form `N*K` where `N` is any integer.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wWe have to find a continuo



### Solution-1 : Naive Way
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe change the heading to Naive Way (TLE)


The naive solution involves traversing all the subset of `nums` whose `length>=2` and checking for `nums[i:j]%K==0` where `i<j` and `nums[i:j]= nums[i]+nums[i+1]+...+nums[j-1]+nums[j]`. While traversing the subsets we explicitily need handle the case `K=0` because `nums[i:j]%K` will throw `DivideByZeroException`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While traversing the subsets we explicitily explicitly to need handle the case



#### Algorithm
1. Create all the subsets of `nums` array whole `length>=2`.
2. Traverse the subsets and check if their sum is a multiple of `K`
3. While traversing the subsets check whether `K=0` which requires sum of the elements in the subset be equal to zero.

<p>
<img align="center" width="800px" alt="Naive Algorithm" src="./../../Images/ContinuousSubarraySum/ContinuousSubArraySum-NaiveAlgo.png">
</p>

This solution will throw `Time Limit Exceeded` error when run on leet code.



### Solution-2 : Dynamic Programming
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not exactly a dynamic programming solution. We are just doing some preprocessing to avoid repeated computation. Any DP solution has two main properties:

  1. It can be broken down into sub-problems and
  2. We can make use of optimal solutions for sub-problems for solving the main problem.

This solution doesn't fit the bill as far as these conditions are concerned. It would be better to name it as Accumulated sum pre-processing or something. At the end of the day, we still check each and every subset for the condition and I don't think there is a recursive element to this problem.

In the previous solution we were repeatedly calculating the sum of the subsets. Here, we try to preprocess the array so that we don't have to calculate the sum everytime. Let us see how we accomplish this.

Let's say

```
sum[0:0] = nums[0]
sum[0:1] = nums[0] + nums[1]
sum[0:2] = nums[0] + nums[1] + nums[2]
sum[0:3] = nums[0] + nums[1] + nums[2] + nums[3]
```
from above, we can conclude that

```
sum[2:3] = nums[2]+nums[3] = sum[0:3] - sum[0:1]
```

If the above procedure is implemented, it will save us from repetitive recomputation of sum of subsets for which we already calculated.

We create a temporary array called `dp` same length as of input where `dp[i]=sum[0:i]`

```
dp[i] = nums[0] + nums[1] +...+ nums[i]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename the array


```

<p>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'd have to change the image to change the DP array to something like a preprocessed array or something.

<img align="center" width="800px" alt="dp" src="./../../Images/ContinuousSubarraySum/dp-creation.png">
</p>

#### Algorithm
1. Create a array called `dp` where `dp[i] = nums[0:i]`
2. We will check each subset for the condition `dp[j]-dp[i]=N*K` where `i<j` and `j-i>1`.
3. The above step is similar to the one we used in Solution-1 except this time we wont need to recompute the sum for each subset generated.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mention the complexity analysis right after this section as is mentioned in the template.


### Solution-3 : Hashmap
Let us assume any two index positions(i,j) and `0<i<j<len(nums)` in `dp` array where

```
dp[i] = p*K ie dp[i]%K=0
dp[j] = q*K ie dp[j]%K=0

```
Let us take a difference of the above two

```
dp[j] - dp[i] = (q-p)*K
```
which transforms to

```
dp[j] - dp[i] = N*K where N is any integer
```

From the above we can conclude that, while traversing the array if we store `dp[i]%K` in a hashmap and check if `dp[j]%K` already exists in hashmap and check if `j-i>1` then we have a continous subarray sum.

The handling of the case `K=0` is same as the previous methods. This is a serious improvement in time complexity from the solution-2.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great to have an Algorithm section like in the previous two approaches to explain this algorithm in more detail. Also, if possible, add a figure here to showcase the algorithm. That would be awesome to have!



#### Complexity Analysis
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's better to mention the complexity analysis for each solution there and then rather than in the end for all three solutions. Also, a one-line explanation can be added in my opinion for each of the complexity sections just to add a bit of clarity even if they are obvious enough


Solution-1

* Time Complexity: `O(N^3)` where `N` is the length of the input.
* Space Complexity: `O(1)`

Solution-2

* Time Complexity: `O(N^2)` where `N` is the length of the input.
* Space Complexity: `O(N)` where `N` is the length of the input. This space is occupied by `dp`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change the name dp to something else


Solution-3

* Time Complexity: `O(N)` where `N` is the length of the input.
* Space Complexity: `O(N+k)` where `N` is the length of the input and `k` is size of the hashmap . The space is occupied by `dp` and `hashmap`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change the name dp to something else


#### Link to OJ
https://leetcode.com/problems/continuous-subarray-sum/

---
Article contributed by [Arihant Sai](https://github.com/Arihant1467)

25 changes: 25 additions & 0 deletions Dynamic-Programming/ContinuousSubarraySum/solution-1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
class Solution {
public:
bool checkSubarraySum(vector<int>& nums, int k) {

int n=nums.size();
for(int i=0;i<n-1;++i){
for(int j=i+1;j<n;++j){
int summation = 0;
for(auto it=nums.begin()+i;it!=nums.begin()+j+1;++it){
summation+=*it;
}

if(k==0){
if(summation==0){
return true;
}
}else if(summation%k==0){
return true;
}
}
}

return false;
}
};
12 changes: 12 additions & 0 deletions Dynamic-Programming/ContinuousSubarraySum/solution-1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class Solution:
def checkSubarraySum(self, nums: List[int], k: int) -> bool:

for i in range(len(nums)-1):
for j in range(i+1,len(nums)):
summation = sum(nums[i:j+1])
if k==0:
if summation==0:
return True
elif summation%k==0:
return True
return False
29 changes: 29 additions & 0 deletions Dynamic-Programming/ContinuousSubarraySum/solution-2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
class Solution(object):
def checkSubarraySum(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: bool
"""
if len(nums)<2:
return False

dp = [0]*len(nums)
dp[0]=nums[0]

for i in range(1,len(nums)):
dp[i]=dp[i-1]+nums[i]

if k==0 and dp[i]==0:
return True
elif k and dp[i]%k==0:
return True

for i in range(0,len(nums)-2):
for j in range(i+2,len(nums)):
if dp[j]-dp[i]==0 and k==0:
return True
elif k and (dp[j]-dp[i])%k==0:
return True

return False
34 changes: 34 additions & 0 deletions Dynamic-Programming/ContinuousSubarraySum/solution-3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
class Solution(object):
def checkSubarraySum(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: bool
"""

dp = [0]*len(nums)
result = {}
dp[0] = nums[0]
for i in range(1,len(nums)):
dp[i] = dp[i-1]+nums[i]

if len(nums)<2:
return False

if k==0:
for i in range(1,len(nums)):
if nums[i]==0 and nums[i-1]==0:
return True
return False

for i in range(len(dp)):
if not i==0 and dp[i]%k==0:
return True
else:
if not (dp[i]%k in result.keys()):
result[dp[i]%k]=i
else:
if i-result[dp[i]%k]>1:
return True

return False
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Images/ContinuousSubarraySum/dp-creation.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Images/ContinuousSubarraySum/question.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,12 @@ There are multiple ways in which you can contribute. There are no "prerequisites
<td>LeetCode</td>
<td><a href="https://github.com/DivyaGodayal/CoderChef-Kitchen/tree/master/Dynamic-Programming/Climbing-Stairs">Link</a></td>
</tr>
<tr>
<td>9</td>
<td>Continuous Subarray Sum</td>
<td>LeetCode</td>
<td><a href="https://github.com/DivyaGodayal/CoderChef-Kitchen/tree/master/Dynamic-Programming/ContinuousSubarraySum">Link</a></td>
</tr>
<tr>
<th colspan="4"><h3>Graphs and Trees</h3></th>
</tr>
Expand Down