
Problem Statement
The task is to determine if an array, nums
, contains at least one subarray (a contiguous segment of the array) that meets the following criteria:
- The length of the subarray is at least two.
- The sum of the elements in the subarray is a multiple of a given integer
k
.
A detailed explanation of the terms:
- A subarray refers to a sequence of elements from the array that are contiguous, meaning they appear in unbroken succession within the array.
- An integer being a multiple of
k
signifies that there exists some integern
such that multiplyingk
byn
results in that integer. This includes zero, as zero is a multiple of every integer.
The function should return true
if such a subarray exists, otherwise, it should return false
.
Examples
Example 1
Input:
nums = [23,2,4,6,7], k = 6
Output:
true
Explanation:
[2, 4] is a continuous subarray of size 2 whose elements sum up to 6.
Example 2
Input:
nums = [23,2,6,4,7], k = 6
Output:
true
Explanation:
[23, 2, 6, 4, 7] is an continuous subarray of size 5 whose elements sum up to 42. 42 is a multiple of 6 because 42 = 7 * 6 and 7 is an integer.
Example 3
Input:
nums = [23,2,6,4,7], k = 13
Output:
false
Constraints
1 <= nums.length <= 105
0 <= nums[i] <= 109
0 <= sum(nums[i]) <= 231 - 1
1 <= k <= 231 - 1
Approach and Intuition
Based on the problem, to find a solution, we need to:
- Check for every possible subarray of length at least two.
- Calculate the sum of each of these subarrays.
- Determine if this sum is divisible by
k
(i.e., sum % k == 0).
The task requires managing large arrays efficiently within the constraints provided, which calls for an approach that reduces repeated calculations:
- Prefix Sum: You can use a prefix sum array to quickly compute the sum of any subarray in constant time after an initial pre-processing step.
- Using Modulus for Efficiency: Instead of computing large sums directly, utilize the remainder (
mod k
) of these sums. Using properties of mod, if at any two different indices in the prefix sum array, the modulus results are equal, the elements between these indices sum up to a multiple ofk
.
Given the constraints:
- The maximum length for
nums
is 10^5, which calls for an efficient solution probably better than O(n^2). - Value
k
will also be large, so directly handling big numbers needs optimized mod operations.
The examples given enlighten the approach:
- Example 1:
[2, 4]
inside[23, 2, 4, 6, 7]
sums up to 6, which is a multiple ofk=6
. The quick sum check here is valid, and the presence of this subarray meets all the conditions. - Example 2: The entire array
[23, 2, 6, 4, 7]
itself sums up to a multiple ofk=6
(42 = 7*6). - Example 3: No subarray with a sum that is a multiple of
k=13
exists, thus returningfalse
.
For each example, ensure the method used can handle the array and k
efficiently, and remember, performance is key due to potentially large inputs.
Solutions
- C++
- Java
- Python
class Solution {
public:
bool hasSubarrayWithSum(vector<int>& arr, int divisor) {
int cumulativeSumModulo = 0;
unordered_map<int, int> moduloIndexMap;
moduloIndexMap[0] = -1;
for (int idx = 0; idx < arr.size(); idx++) {
cumulativeSumModulo = (cumulativeSumModulo + arr[idx]) % divisor;
if (moduloIndexMap.find(cumulativeSumModulo) != moduloIndexMap.end()) {
if (idx - moduloIndexMap[cumulativeSumModulo] > 1) {
return true;
}
} else {
moduloIndexMap[cumulativeSumModulo] = idx;
}
}
return false;
}
};
This solution tackles the problem of finding a continuous subarray within an array that sums to a multiple of a given number (divisor
). The implementation is in C++ and uses a combination of a cumulative sum approach and hashing to efficiently solve the problem.
- The function
hasSubarrayWithSum
accepts a vectorarr
and an integerdivisor
as parameters. - It initializes
cumulativeSumModulo
to keep track of the cumulative sum modulodivisor
, and anunordered_map<int, int>
calledmoduloIndexMap
to store the first occurrence index of each modulo value. moduloIndexMap
is initialized with the key0
set to-1
to handle the edge case where a valid subarray begins from index0
.- A for loop iterates through each element in the array:
- The
cumulativeSumModulo
is updated by adding the current array element (arr[idx]
) and taking modulodivisor
. - If the current
cumulativeSumModulo
exists inmoduloIndexMap
, it checks if the subarray length is greater than 1 (as a valid subarray must contain at least two elements).- If so, the function returns
true
, indicating that a qualifying subarray has been found.
- If so, the function returns
- If the
cumulativeSumModulo
is not found inmoduloIndexMap
, the current index is added to the map withcumulativeSumModulo
as the key.
- The
- If the loop completes without finding any such subarray, the function returns
false
.
This solution efficiently checks subarrays by leveraging the properties of cumulative sums and the modulo operation, combined with map lookups to avoid redundant calculations. This approach significantly reduces complexity, especially compared to a naive method involving nested loops.
import java.util.HashMap;
class Solution {
public boolean hasSubarraySum(int[] elements, int divisor) {
int cumulativeSumMod = 0;
HashMap<Integer, Integer> modIndexMap = new HashMap<>();
modIndexMap.put(0, -1);
for (int index = 0; index < elements.length; index++) {
cumulativeSumMod = (cumulativeSumMod + elements[index]) % divisor;
if (modIndexMap.containsKey(cumulativeSumMod)) {
// checks subarray size is greater than 1
if (index - modIndexMap.get(cumulativeSumMod) > 1) {
return true;
}
} else {
// record the current index for this mod result
modIndexMap.put(cumulativeSumMod, index);
}
}
return false;
}
}
The provided Java solution addresses the problem of determining whether a continuous subarray of given elements, whose sum is divisible by a specified divisor, exists within a given array of integers. The solution leverages a HashMap to store modulo results derived from the cumulative sum of elements processed sequentially.
Initially, insert a key-value pair (0, -1) into the HashMap, allowing straightforward validation for cases where an early subarray sum is exactly divisible by the divisor.
Iterate through the elements, computing a running cumulative sum modulated by the divisor to maintain results within the necessary range and store or verify these results:
- For each element, update the cumulative sum, modulo by the divisor.
- Check the HashMap to see whether the same remainder has been encountered previously:
- If yes, ensure that the subarray formed between the current and previously stored index is of size greater than one (i.e., the difference between indices is more than one). If this holds true, the function immediately returns
true
. - If no match is found for the remainder, store the current index mapped to the current remainder in the HashMap.
- If yes, ensure that the subarray formed between the current and previously stored index is of size greater than one (i.e., the difference between indices is more than one). If this holds true, the function immediately returns
The function returns
false
if no qualifying subarray is found by the end of the iteration through the elements.
The solution is efficient due to its use of a HashMap, allowing constant time complexity operations for adding and checking entries, while overall processing of the elements is linear in time complexity relative to the array size. This method provides a powerful way to deal with cumulative sums modulated by a divisor in array analysis problems.
class Solution:
def hasSubarrayWithSum(self, values, divisor):
current_modulo = 0
encountered_modulo = {0: -1}
for idx in range(len(values)):
current_modulo = (current_modulo + values[idx]) % divisor
if current_modulo in encountered_modulo:
if idx - encountered_modulo[current_modulo] > 1:
return True
else:
encountered_modulo[current_modulo] = idx
return False
The provided Python code defines a method, hasSubarrayWithSum
, which checks if there exists a continuous subarray within a given list, values
, whose sum is divisible by another input, divisor
. This method belongs to the Solution
class.
Here's a step-by-step walkthrough of how the method functions:
- Initialize
current_modulo
to zero - This variable tracks the cumulative sum's remainder when divided by thedivisor
. - Create a dictionary,
encountered_modulo
, to store the remainders and their corresponding indices. It starts with the remainder 0 at index -1. - Iterate through the list using the index. For each element:
- Calculate the new
current_modulo
as the sum of the currentcurrent_modulo
and the current value from the list, then take this sum modulo thedivisor
. - Check if
current_modulo
has been encountered before:- If it has, and if the difference between the current index and the stored index of
current_modulo
is greater than 1, return True.
- If it has, and if the difference between the current index and the stored index of
- If
current_modulo
has not been encountered before, updateencountered_modulo
with the current index.
- Calculate the new
- After completing the loop, if no such subarray is found, return False.
This approach uses a hashmap to optimize checking for previously encountered remainders, ensuring that the function efficiently determines if the desired subarray exists.
No comments yet.