Check if a Subarray exists with sums as a multiple of k
Last Updated :
27 Oct, 2023
Given a list of non-negative numbers and a target integer k, write a function to check if the array has a continuous subarray of size at least 2 that sums up to the multiple of k, that is, sums up to n*k where n is also an integer.
Note: The length of the array won’t exceed 10,000. You may assume the sum of all the numbers is in the range of a signed 32-bit integer.
Examples:
Input: [23, 2, 4, 6, 7], k = 6
Output: True
Explanation: Because [2, 4] is a continuous subarray of size 2 and sums up to 6.
Input: [23, 2, 6, 4, 7], k = 6
Output: True
Explanation: Because [23, 2, 6, 4, 7] is a continuous subarray of size 5 and sums up to 42.
Naive Approach: The basic way to solve the problem is as follows:
A straightforward way to tackle this problem is, by examining every subarray that has a size of least 2 and determining the sum of each one. If we find any subarray whose sum’s divisible, by k we will answer with True; otherwise, we will respond with False.
Time Complexity: O(n^2) since there can be O(n^2) subarrays to evaluate.
Auxiliary Space: O(n^2)
Efficient Approach: To solve the problem follow the below idea:
The idea is to use a prefix sum array to keep track of the cumulative sum of the input array modulo k (i.e., the remainder after dividing by k). We’ll also use a dictionary (hash map) to store the remainder values and their corresponding indices in the prefix sum array.
Follow the steps to solve the problem:
- Initialize a prefix sum array presum with length n+1, where n is the length of the input array.
- Initialize a dictionary seen to store the index of each remainder value.
- Traverse the input array and compute the prefix sum array presum. For each prefix sum, compute presum[i] = (presum[i – 1] + arr[i – 1]) % k.
- For each index i in the prefix sum array, check if the current remainder value presum[i] is already in the seen dictionary.
- If it is, check if the distance between the current index i and the index stored in seen[presum[i]] is greater than 1. If yes, we found a subarray with a sum that is a multiple of k, so we return True.
- If it’s not in the dictionary, add the current remainder value presum[i] to the seen dictionary with the current index i.
- If we have traversed the entire prefix sum array without finding a valid subarray, return False.
Dry Run:
Let’s run through the examples you provided to understand how this approach works:
Input: nums = [23, 2, 4, 6, 7], k = 6
To start off we initialize a dictionary called “seen” with the key value pair of {0; 1}. Additionally, we set the prefix_sum” to zero.
Let’s go through the elements:
- Firstly, we process the number 23. Here’s what happens.
- We update the value of “prefix_sum” to be equal to 23.
- Next, we calculate the residual by finding the remainder when dividing 23 by 6. In this case it is equal to 5. Since this residual (5) is not present in our “seen” dictionary yet we add it along with its corresponding index (0). So now our “seen” dictionary looks like this:
{0: -1, 5: 0}.
- Moving on to the element which’s number 2
- We update the value of “prefix_sum” by adding 2 to its current value of 23. Therefore, it becomes equal to 25.
- Similar to before we calculate the residual by finding the remainder when dividing this prefix sum (25) by k (which’s still equal to 6 in this case). The calculated residual turns out to be 1.
- As for adding it into our “seen” dictionary since it’s not present already. After doing our updated “seen” dictionary looks like this; {0: -1, 5:0, 1:1}.
- Finally, we process the element which’s number 4
- Updating our prefix sum once again by adding 4 to its current value of 29 results in a new prefix sum of 33.
- Calculating its corresponding residual using modulo operation with k (still being equal to six) gives us a value of 5.
- However, this time we notice that the residual of 5 is already present in our “seen” dictionary at index 0. This means we have found a subarray [2, 4] whose sum adds up to be a multiple of k (which’s six).
- Therefore the output for this example is True.
Below is the implementation of above approach in python:
C++
#include <iostream>
#include <unordered_map>
#include <vector>
bool subarraySum(std::vector< int >& nums, int k) {
std::unordered_map< int , int > seen;
seen[0] = -1;
int prefixSum = 0;
for ( int i = 0; i < nums.size(); ++i) {
prefixSum += nums[i];
int residual = prefixSum % k;
if (seen.find(residual) != seen.end() && i - seen[residual] > 1) {
return true ;
}
if (seen.find(residual) == seen.end()) {
seen[residual] = i;
}
}
return false ;
}
int main() {
std::vector< int > nums1 = {23, 2, 4, 6, 7};
std::vector< int > nums2 = {23, 2, 6, 4, 7};
std::cout << std::boolalpha << subarraySum(nums1, 6) << std::endl;
std::cout << std::boolalpha << subarraySum(nums2, 6) << std::endl;
return 0;
}
|
Java
import java.util.HashMap;
public class Main {
public static boolean subarraySum( int [] nums, int k) {
HashMap<Integer, Integer> seen = new HashMap<>();
seen.put( 0 , - 1 );
int prefixSum = 0 ;
for ( int i = 0 ; i < nums.length; ++i) {
prefixSum += nums[i];
int residual = prefixSum % k;
if (seen.containsKey(residual) && i - seen.get(residual) > 1 ) {
return true ;
}
if (!seen.containsKey(residual)) {
seen.put(residual, i);
}
}
return false ;
}
public static void main(String[] args) {
int [] nums1 = { 23 , 2 , 4 , 6 , 7 };
int [] nums2 = { 23 , 2 , 6 , 4 , 7 };
System.out.println(subarraySum(nums1, 6 ));
System.out.println(subarraySum(nums2, 6 ));
}
}
|
Python
def subarray_sum(nums, k):
seen = { 0 : - 1 }
prefix_sum = 0
for i, num in enumerate (nums):
prefix_sum + = num
residual = prefix_sum % k
if residual in seen and i - seen[residual] > 1 :
return True
if residual not in seen:
seen[residual] = i
return False
print (subarray_sum([ 23 , 2 , 4 , 6 , 7 ], 6 ))
print (subarray_sum([ 23 , 2 , 6 , 4 , 7 ], 6 ))
|
C#
using System;
using System.Collections.Generic;
class Program
{
static bool SubarraySum(List< int > nums, int k)
{
Dictionary< int , int > seen = new Dictionary< int , int >();
seen[0] = -1;
int prefixSum = 0;
for ( int i = 0; i < nums.Count; ++i)
{
prefixSum += nums[i];
int residual = prefixSum % k;
if (seen.ContainsKey(residual) && i - seen[residual] > 1)
{
return true ;
}
if (!seen.ContainsKey(residual))
{
seen[residual] = i;
}
}
return false ;
}
static void Main()
{
List< int > nums1 = new List< int > { 23, 2, 4, 6, 7 };
List< int > nums2 = new List< int > { 23, 2, 6, 4, 7 };
Console.WriteLine(SubarraySum(nums1, 6));
Console.WriteLine(SubarraySum(nums2, 6));
}
}
|
Javascript
function subarraySum(nums, k) {
let seen = new Map();
let prefixSum = 0;
for (let i = 0; i < nums.length; i++) {
prefixSum += nums[i];
let residual = prefixSum % k;
if (seen.has(residual) && i - seen.get(residual) > 1) {
return true ;
}
if (!seen.has(residual)) {
seen.set(residual, i);
}
}
return false ;
}
console.log(subarraySum([23, 2, 4, 6, 7], 6));
console.log(subarraySum([23, 2, 6, 4, 7], 6));
|
Time Complexity: O(n), where n is the length of the input array.
Auxiliary Space: O(min(n, k)), where n is the length of the input array and k is the target integer.
Share your thoughts in the comments
Please Login to comment...