Open In App

Check if a Subarray exists with sums as a multiple of k

Last Updated : 27 Oct, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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 “seendictionary 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>
 
// Function to check if there exists a subarray with a sum divisible by k
bool subarraySum(std::vector<int>& nums, int k) {
    // Create a dictionary to store the residual values and their indices
    std::unordered_map<int, int> seen;
    seen[0] = -1;  // Initialize with a dummy value
     
    int prefixSum = 0;  // Initialize the prefix sum
     
    for (int i = 0; i < nums.size(); ++i) {
        prefixSum += nums[i];  // Calculate the prefix sum
        int residual = prefixSum % k;  // Calculate the residual value
         
        // If the same residual value has been seen before and the subarray size is at least 2
        if (seen.find(residual) != seen.end() && i - seen[residual] > 1) {
            return true;
        }
         
        // If the residual value is not seen before, add it to the dictionary
        if (seen.find(residual) == seen.end()) {
            seen[residual] = i;
        }
    }
     
    return false;
}
 
int main() {
    // Test cases
    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) {
        // Create a dictionary to store the residual values and their indices
        HashMap<Integer, Integer> seen = new HashMap<>();
        seen.put(0, -1);  // Initialize with a dummy value
         
        int prefixSum = 0// Initialize the prefix sum
         
        for (int i = 0; i < nums.length; ++i) {
            prefixSum += nums[i];  // Calculate the prefix sum
            int residual = prefixSum % k;  // Calculate the residual value
             
            // If the same residual value has been seen before and the subarray size is at least 2
            if (seen.containsKey(residual) && i - seen.get(residual) > 1) {
                return true;
            }
             
            // If the residual value is not seen before, add it to the dictionary
            if (!seen.containsKey(residual)) {
                seen.put(residual, i);
            }
        }
         
        return false;
    }
     
    public static void main(String[] args) {
        // Test cases
        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)); 
    }
}
//Contributed by Aditi


Python




# Python program for the above approach:
def subarray_sum(nums, k):
 
    # Create a dictionary to
    # store the residual values
    # and their indices
    seen = {0: -1}
 
    # Initialize the prefix sum
    prefix_sum = 0
 
    for i, num in enumerate(nums):
        prefix_sum += num
 
        # Calculate the residual value
        residual = prefix_sum % k
 
        # If the same residual value has been
        # seen before and the subarray
        # size is at least 2
        if residual in seen and i - seen[residual] > 1:
            return True
 
        # If the residual value is
        # not seen before,
        # add it to the dictionary
        if residual not in seen:
            seen[residual] = i
 
    return False
 
 
# Test cases
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
{
      // Function to check if there exists a subarray with a sum divisible by k
    static bool SubarraySum(List<int> nums, int k)
    {   
          // Create a dictionary to store the residual values and their indices
        Dictionary<int, int> seen = new Dictionary<int, int>();
       
          // Initialize with a dummy value
        seen[0] = -1;
       
          // Initialize the prefix sum
        int prefixSum = 0;
        for (int i = 0; i < nums.Count; ++i)
        {
              // Calculate the prefix sum
            prefixSum += nums[i];
           
              // Calculate the residual value
            int residual = prefixSum % k;
           
          // If the same residual value has been seen before and the subarray size is at least 2
            if (seen.ContainsKey(residual) && i - seen[residual] > 1)
            {
                return true;
            }
           
              // If the residual value is not seen before, add it to the dictionary
            if (!seen.ContainsKey(residual))
            {
                seen[residual] = i;
            }
        }
        return false;
    }
 
      // Driver code
    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




// JavaScript program for the above approach:
function subarraySum(nums, k) {
   
  // Create a map to store the residual values
  // and their indices
  let seen = new Map();
   
  // Initialize the prefix sum
  let prefixSum = 0;
   
  for (let i = 0; i < nums.length; i++) {
    prefixSum += nums[i];
     
    // Calculate the residual value
    let residual = prefixSum % k;
     
    // If the same residual value has been
    // seen before and the subarray
    // size is at least 2
    if (seen.has(residual) && i - seen.get(residual) > 1) {
      return true;
    }
     
    // If the residual value is
    // not seen before,
    // add it to the map
    if (!seen.has(residual)) {
      seen.set(residual, i);
    }
  }
   
  return false;
}
 
// Test cases
console.log(subarraySum([23, 2, 4, 6, 7], 6));
console.log(subarraySum([23, 2, 6, 4, 7], 6));
 
// This code is contributed by Sakshi


Output

true
true

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.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads