medium Make Sum Divisible by P
Problem Statement
Given an array nums containing the positive integers, remove the smallest subarray (maybe empty) from nums such that the sum of the remaining elements is divisible by p. You are not allowed to remove the whole array.
Return the length of the smallest subarray that you need to remove, or -1 if it's not possible.
A subarray is a contiguous sequence of elements in the array.
Examples
Example 1:
- Input:
nums = [5, 9, 7, 8], P = 5 - Expected Output:
1 - Justification: Removing the subarray
[9]results in a new array[5, 7, 8]whose sum is20, which is divisible by5.
Example 2:
- Input:
nums = [6, 4, 3, 2, 7, 6, 2], P = 10 - Expected Output:
0 - Justification: We don't need to remove any element from the array, as the sum of all array elements is divisible by 10.
Example 3:
- Input:
nums = [8, 19, 4, 3], P = 10 - Expected Output:
1 - Justification: By removing the subarray
[4], we get a new array[8, 19, 3]with a sum of30, Which is divisible by 10.
Try it yourself
Try solving this question here:
✅ Solution Make Sum Divisible by P
Problem Statement
Given an array nums containing the positive integers, remove the smallest subarray (maybe empty) from nums such that the sum of the remaining elements is divisible by p. You are not allowed to remove the whole array.
Return the length of the smallest subarray that you need to remove, or -1 if it's not possible.
A subarray is a contiguous sequence of elements in the array.
Examples
Example 1:
- Input:
nums = [5, 9, 7, 8], P = 5 - Expected Output:
1 - Justification: Removing the subarray
[9]results in a new array[5, 7, 8]whose sum is20, which is divisible by5.
Example 2:
- Input:
nums = [6, 4, 3, 2, 7, 6, 2], P = 10 - Expected Output:
0 - Justification: We don't need to remove any element from the array, as the sum of all array elements is divisible by 10.
Example 3:
- Input:
nums = [8, 19, 4, 3], P = 10 - Expected Output:
1 - Justification: By removing the subarray
[4], we get a new array[8, 19, 3]with a sum of30, Which is divisible by 10.
Solution
To solve this problem, we adopt a two-pronged strategy focusing on prefix sums and hash mapping. Initially, we calculate the total sum of the array and determine the excess or deficit with respect to P required to make the sum divisible by P. Recognizing that removing a subarray to adjust the total sum to a multiple of P mirrors finding a segment whose sum equals this excess or deficit, we proceed to track prefix sums and their indices.
This approach is underpinned by the insight that if two prefix sums have the same remainder when divided by P, the segment between them contributes a sum that is a multiple of P. Consequently, by maintaining a hash map of the earliest occurrence of each remainder, we can efficiently identify the minimum length of a subarray that, when removed, leaves the array's sum divisible by P. This method is not only intuitive but also leverages the efficiency of hash maps for quick lookups, rendering it a potent solution for the problem at hand.
Step-by-Step Algorithm
-
Initialize Variables:
- Calculate the total sum of the array elements and find its remainder when divided by
P(totalSum % P). This will help in identifying the excess amount that needs to be addressed by removing a subarray. - Initialize an empty hash map (
remainderMap) to store the prefix sum remainders as keys and their corresponding indices as values. Insert a base case into the hash map with0as the key and-1as the value. This represents the prefix sum before the array starts, facilitating scenarios where the required subarray starts from index0. - Define variables for the current sum (
currSum), set initially to0, and the minimum length of the subarray to be removed (minLen), set initially to an arbitrarily large value (likeInteger.MAX_VALUEin Java orfloat('inf')in Python).
- Calculate the total sum of the array elements and find its remainder when divided by
-
Iterate Through the Array:
- For each element in the array, add it to
currSumand calculate the remainder ofcurrSumwhen divided byP. - Calculate the complement of the current remainder with respect to the total excess (
(currSum - totalSum + P) % P). This step identifies what remainder we need to find in the hash map to form a continuous subarray whose removal could potentially make the total sum divisible byP.
- For each element in the array, add it to
-
Update HashMap and Minimum Length:
- If the complement calculated in the previous step exists in
remainderMap, it means there exists a previous prefix sum that, when subtracted from the current prefix sum, results in a sum that is a multiple ofP. Calculate the length of this subarray and updateminLenif this length is smaller than the currentminLen. - Update
remainderMapwith the current prefix sum remainder as the key and the current index as the value. This step is crucial for keeping track of the earliest occurrence of each remainder.
- If the complement calculated in the previous step exists in
-
Finalize Result:
- After iterating through the entire array, check if
minLenis still set to its initial large value or equals the length of the array. If so, return-1, indicating that it's not possible to remove any subarray to make the sum divisible byP. - Otherwise, return
minLenas the minimum length of the subarray that needs to be removed.
- After iterating through the entire array, check if
Algorithm Walkthrough
Let's consider the input: nums = [5, 9, 7, 8], P = 5
-
Total Sum Calculation:
- Total sum of
[5, 9, 7, 8]is29.29 % 5 = 4. So, we need to adjust the total sum to be divisible by5by addressing this excess of4.
- Total sum of
-
Initialization:
remainderMap = {0: -1}totalSum % P = 4,currSum = 0,minLen = inf
-
Iteration 1:
currSumwith first element5:currSum = (0 + 5) % 5 = 0- Complement to find:
(0 - 4 + 5) % 5 = 1. Complement1doesn't exist inremainderMap. remainderMapupdated to{0: 0}
-
Iteration 2:
currSumwith second element9:currSum = (0 + 9) % 5 = 4- Complement to find:
(4 - 4 + 5) % 5 = 0. Complement0exists inremainderMap. - Update
minLento1 - 0 = 1. remainderMapupdated to{0: 0, 4: 1}
-
Iteration 3:
currSumwith third element7:currSum = (4 + 7) % 5 = 1- Complement to find:
(1 - 4 + 5) % 5 = 2. Complement2does not exist inremainderMap. remainderMapupdated to{0: 0, 4: 1, 1: 2}
-
Iteration 4:
currSumwith fourth element8:currSum = (1 + 8) % 5 = 4- Complement to find:
(4 - 4 + 5) % 5 = 0. Complement0exists inremainderMap. minLencould be updated to3 - 0 = 3, but since1 < 3,minLenremains1.remainderMapfinal{0: 0, 4: 1, 1: 2}
-
Final Result:
- The minimum length of the subarray that needs to be removed to make the sum divisible by
Pis1. This corresponds to the removal of[9]to adjust the sum.
- The minimum length of the subarray that needs to be removed to make the sum divisible by
Code
import java.util.HashMap; // Import statement for HashMap
public class Solution {
// Method to find the minimum subarray length to remove for making the sum divisible by P
public int minSubarray(int[] nums, int P) {
int totalSum = 0;
// Calculate the total sum of the array elements
for (int num : nums) {
totalSum = (totalSum + num) % P;
}
// If totalSum is already divisible by P, no need to remove any subarray
if (totalSum == 0) return 0;
// HashMap to store the earliest index where each remainder is found
HashMap<Integer, Integer> remainderMap = new HashMap<>();
remainderMap.put(0, -1); // Base case: to handle the case when subarray starts from index 0
int minLen = Integer.MAX_VALUE, currSum = 0;
// Iterate through the array to find the minimum length subarray to remove
for (int i = 0; i < nums.length; i++) {
currSum = (currSum + nums[i]) % P;
int complement = (currSum - totalSum + P) % P;
// If complement exists in remainderMap, calculate the possible minimum length
if (remainderMap.containsKey(complement)) {
minLen = Math.min(minLen, i - remainderMap.get(complement));
}
// Update the remainderMap with the current remainder and its index
remainderMap.put(currSum, i);
}
// Return the minimum length found, ensuring it's not the entire array length
return minLen == Integer.MAX_VALUE || minLen == nums.length ? -1 : minLen;
}
// Main method to test the solution with example inputs
public static void main(String[] args) {
Solution solution = new Solution();
System.out.println(solution.minSubarray(new int[] { 5, 9, 7, 8 }, 5));
System.out.println(
solution.minSubarray(new int[] { 6, 4, 3, 2, 7, 6, 2 }, 10)
);
System.out.println(solution.minSubarray(new int[] { 8, 19, 4, 3 }, 10));
}
}
Complexity Analysis
- Time Complexity: The algorithm iterates through the array once, making the time complexity
, where Nis the length of the array. The operations within each iteration (e.g., updating the hash map, calculating remainders) are constant time. - Space Complexity: The space complexity is also
due to the hash map that stores up to Ndifferent remainders and their indices.
🤖 Don't fully get this? Learn it with Claude
Stuck on Make Sum Divisible by P? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Progressively stronger hints — you still solve it.
I'm working on the problem **Make Sum Divisible by P** (DSA). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
See the technique, not just code.
Explain the optimal approach to **Make Sum Divisible by P** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Catch bugs, edge cases, sub-optimality.
I'll paste my solution to **Make Sum Divisible by P**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Lock in recognition with look-alikes.
Give me 2 problems that use the SAME underlying pattern as **Make Sum Divisible by P**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.