Make Sum Divisible by P

Updated on 16 June, 2025
Make Sum Divisible by P header image

Problem Statement

In this task, you are provided with an array of positive integers named nums. Your goal is to remove the smallest subarray (which can also be empty) such that the sum of the remaining elements is divisible by a given integer p. However, it's important to note that removing the entire array is not permissible.

The function should return the length of the smallest subarray that needs to be removed to achieve the above condition. If achieving this condition is impossible, then the function should return -1.

A subarray, for the purposes of this problem, can be understood to be any contiguous part of the given array, and the aim is to find the minimal length of such a part whose removal helps achieve divisibility of the sum of the array by p.

Examples

Example 1

Input:

nums = [3,1,4,2], p = 6

Output:

1

Explanation:

The sum of the elements in nums is 10, which is not divisible by 6. We can remove the subarray [4], and the sum of the remaining elements is 6, which is divisible by 6.

Example 2

Input:

nums = [6,3,5,2], p = 9

Output:

2

Explanation:

We cannot remove a single element to get a sum divisible by 9. The best way is to remove the subarray [5,2], leaving us with [6,3] with sum 9.

Example 3

Input:

nums = [1,2,3], p = 3

Output:

0

Explanation:

Here the sum is 6. which is already divisible by 3. Thus we do not need to remove anything.

Constraints

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 109
  • 1 <= p <= 109

Approach and Intuition

To solve the problem efficiently, let's break down the approach using the details from the examples:

  1. Compute Total Array Sum

    • Calculate the sum of the entire array. If this sum is already divisible by p, the function should return 0 as no element needs to be removed.
  2. Finding the Target Modulo

    • Subtract the total sum modulo p from p itself to determine the deficit that needs to be matched by the sum of a potential subarray to be removed.
  3. Utilizing Prefix Sums and Hashmap

    • Create a prefix sum array which keeps running sums of elements from the start of nums as you traverse through it.
    • Use a hashmap to store the first occurrence of each mod value of the prefix sums to efficiently find any subsequences which match the required mod value later.
  4. Identifying the Shortest Subarray

    • For each prefix sum, compute its mod value with p and determine how this value can be adjusted to the desired mod value (determined in step 2) by examining differences between current and previously encountered mod values in your map.
    • The objective here is to identify minimal gaps which align with the needed deficit to make the total sum divisible by p.
  5. Handling Edge Cases

    • If such a subarray is found, update the minimum length of this subarray if it's smaller than previously encountered ones. If no such subarray can be found throughout the process, return -1.

By following this methodology, this ensures that we efficiently find the smallest subarray, if at all possible, whose removal leads to the remaining elements having a sum divisible by p.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    int minimalSubsequence(vector<int>& vec, int divisor) {
        int length = vec.size();
        int sumT = 0;
    
        // Calculating total sum and modulus
        for (auto val : vec) {
            sumT = (sumT + val) % divisor;
        }
    
        int residue = sumT % divisor;
        if (residue == 0) return 0;  // If divisible, no need for sub-array
    
        // Mapping to store prefix sums modulo divisor
        unordered_map<int, int> prefixMods;
        prefixMods[0] = -1;  // Base case for full array computation
        int prefixSum = 0, smallestLength = length;
    
        // Iterating over the elements
        for (int idx = 0; idx < length; ++idx) {
            prefixSum = (prefixSum + vec[idx]) % divisor;
    
            // Calculating required sum to form proper subarray
            int neededMod = (prefixSum - residue + divisor) % divisor;
    
            // Check if there's a matching prefix
            if (prefixMods.count(neededMod)) {
                smallestLength = min(smallestLength, idx - prefixMods[neededMod]);
            }
    
            // Storing index of each encountered mod
            prefixMods[prefixSum] = idx;
        }
    
        // Outcome of search: either minimal length or -1 if no valid subarray
        return smallestLength == length ? -1 : smallestLength;
    }
};

The "Make Sum Divisible by P" task in C++ is addressed using a class named Solution that provides a method called minimalSubsequence. The issue focuses on reducing the size of a subsequence in a vector such that the sum of its elements results in a number divisible by a specified divisor.

  • Initialize variables for vector length, total sum, and residue.
  • Compute the aggregate modulo of the vector to decide the residue for divisibility check. If residue is zero, the entire array sum is already divisible, return 0.
  • Utilize an unordered map to track prefix sums modulo the divisor for optimizing the search of subsequences.
  • Iterate through the vector, computing the prefix sum at each step and adjust it using the modulo operation.
  • Calculate the required modification to current prefix sum (neededMod) to find a subsequence that formats the residue into a number divisible by the divisor.
  • Check for any prior occurrence of the needed modification in the map.
    • If it exists, compare and update the smallest length of the subsequence found so far.
    • If no valid subsequence exists by the end of the loop, the function returns -1.
  • Update the map with the current prefix sum and the respective index for future references.

This method ensures efficient computation by leveraging modulo arithmetic and hash mapping to minimize the need to inspect each potential subsequence directly, thereby optimizing the performance for large input vectors.

java
class Solution {
    
    public int minimumSubarrayLength(int[] arr, int divisor) {
        int arraySize = arr.length;
        int aggregateSum = 0;
    
        // Calculate overall sum and the remainder that needs to be addressed
        for (int value : arr) {
            aggregateSum = (aggregateSum + value) % divisor;
        }
    
        int requiredRemainder = aggregateSum % divisor;
        if (requiredRemainder == 0) {
            return 0; // The entire array is already divisible by divisor
        }
    
        // Mapping to store modulo results of prefix sums
        HashMap<Integer, Integer> remainderMap = new HashMap<>();
        remainderMap.put(0, -1); // Helps to include prefix sum that meets criteria exactly
        int sumSoFar = 0;
        int shortestLength = arraySize;
    
        // Process each element in the given array
        for (int i = 0; i < arraySize; ++i) {
            sumSoFar = (sumSoFar + arr[i]) % divisor;
    
            // Determine the required sum to form the appropriate subarray
            int neededRemainder = (sumSoFar - requiredRemainder + divisor) % divisor;
    
            // Check if the needed remainder previously occurred
            if (remainderMap.containsKey(neededRemainder)) {
                shortestLength = Math.min(shortestLength, i - remainderMap.get(neededRemainder));
            }
    
            // Update the mapping with current index and sum mod
            remainderMap.put(sumSoFar, i);
        }
    
        // Check if we found a valid subarray
        return shortestLength == arraySize ? -1 : shortestLength;
    }
}

The Java solution provided aims to find the minimum length of a subarray such that its sum, when removed from the original array, makes the complete array's sum divisible by a given divisor, P. The process implemented in the code ensures an efficient handling of this problem using a combination of modular arithmetic and hashmap for prefix sum management.

First, compute the total sum of elements modulo P (divisor). Determine the requiredRemainder to adjust the total sum to make it divisible by P. If the requiredRemainder is zero, the array sum is already divisible, and no subarray needs to be removed, hence the function returns 0.

A hashmap (remainderMap) is utilized to store the indices of prefix sums modulo P. This helps in rapidly checking if there exists any subarray whose removal will adjust the array's sum as required. By iterating through the array:

  • Calculate the running sum mod P for each element.
  • Compute the difference required to reach the requiredRemainder, adjusted for modular arithmetic.
  • If this adjusted difference has been seen before in the remainderMap, it implies that the subarray from the last occurrence to the current index can potentially be the subarray to be removed. If so, update the shortestLength if this subarray is shorter than previously found ones.
  • Store each new running sum mod P in the remainderMap with its corresponding index.

Finally, if shortestLength was updated (meaning a suitable subarray was found), return its length. If it remains equal to the length of the array, it indicates no such subarray exists, hence return -1.

This approach guarantees that the solution is efficient, avoiding any brute-force method that would significantly increase computational complexity, making it suitable for large data sets.

python
class Solution:
    def smallestSubarray(self, vals: List[int], divisor: int) -> int:
        size = len(vals)
        sum_total = 0
    
        # Compute the total sum and target modulus
        for val in vals:
            sum_total = (sum_total + val) % divisor
    
        remainder_target = sum_total % divisor
        if remainder_target == 0:
            return 0  # The array already meets the condition
    
        # Dictionary to keep prefix sum modulus
        prefix_mod_map = {
            0: -1  # Initial case for whole prefix as a solution
        }
        prefix_sum = 0
        smallest_size = size
    
        # Traverse through the array
        for idx in range(size):
            prefix_sum = (prefix_sum + vals[idx]) % divisor
    
            # Calculate necessary complement
            necessary = (prefix_sum - remainder_target + divisor) % divisor
    
            # Check if this complement exists
            if necessary in prefix_mod_map:
                smallest_size = min(smallest_size, idx - prefix_mod_map[necessary])
    
            # Update the current modulo result and its index
            prefix_mod_map[prefix_sum] = idx
    
        # Final decision between no subarray found or the smallest size
        return -1 if smallest_size == size else smallest_size

You need to find the smallest subarray such that its sum is divisible by a given number, divisor. The function smallestSubarray employs a combination of prefix sums and the modulo operation to efficiently solve this problem. Here's a concise overview of the approach and how the implementation works:

  • Calculate Total Sum Modulus: Start by determining the total sum of the array modulo the divisor. If this value is 0, the entire array already meets the conditions and 0 is returned.

  • Use HashMap for Prefix Moduli: Introduce a dictionary, prefix_mod_map, to store the indices of various prefix sum moduli. Initialize it with the key 0 set to -1 to handle edge cases effectively.

  • Iterate and Update Prefix Sums: For each element in the array, update the rolling prefix sum modulo the divisor. Determine the necessary complement that when added to this prefix sum would result in a modulus equal to the target remainder.

  • Check for Complements: For each updated prefix sum, check if the complement (to reach the necessary modulo state) exists within your map. If so, compute the length of the subarray ending at the current index that would have this sum. Keep track of the smallest such subarray length.

  • Decision Point: Finally, if no valid subarray is found that adjusts the sum to be divisible by the divisor, return -1. Otherwise, return the length of the smallest valid subarray found.

This method efficiently resolves the problem by combining mathematical properties of moduli with a strategic use of hashing to avoid overly complex operations.

Comments

No comments yet.