#21 1590. ๐งฎ Make Sum Divisible by P Using the Smallest Subarray Removal ๐
In this blog post, weโll solve an interesting problem where the goal is to remove the smallest subarray from a list of integers such that the remaining sum is divisible by a given number, p. Weโll explore both the problem and its optimized solution using a hash map.
Letโs break it down step by step! ๐
๐ Problem Statement
We are given an array of positive integers nums and an integer p. Our task is to remove the smallest subarray (possibly empty) such that the sum of the remaining elements is divisible by p.
- If itโs not possible to make the sum divisible by
p, we return-1. - A subarray is defined as a contiguous block of elements in the array.
Example 1:
Input: nums = [3,1,4,2], p = 6
Output: 1
Explanation: The sum of 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].
Example 3:
Input: nums = [1,2,3], p = 3
Output: 0
Explanation: The sum of nums is 6, which is already divisible by 3.
No need to remove anything.
Hereโs the basic solution, which solves the problem in a straightforward but inefficient manner. It uses brute force to check every possible subarray and tries to remove it, checking if the sum of the remaining elements is divisible by p.
๐ Basic Solution: Brute Force Approach
The basic idea is to iterate over every possible subarray, remove it, and check if the remaining sum is divisible by p. This approach works for small inputs but is inefficient for larger arrays due to its time complexity.
๐ Basic Python Code:
class Solution:
def minSubarray(self, nums: List[int], p: int) -> int:
total_sum = sum(nums)
remainder = total_sum % p
# If the total sum is divisible by p, no removal needed
if remainder == 0:
return 0
n = len(nums)
min_len = n
# Try removing every possible subarray
for i in range(n):
for j in range(i, n):
subarray_sum = sum(nums[i:j+1])
if (total_sum - subarray_sum) % p == 0:
min_len = min(min_len, j - i + 1)
# Return -1 if no valid subarray was found
return min_len if min_len < n else -1
๐ Explanation of the Code:
- Calculate Total Sum: First, we calculate the total sum of the array and check its remainder when divided by
p. - Early Exit: If the total sum is divisible by
p, we return0since no subarray needs to be removed. - Brute Force Subarray Removal: We iterate through every possible subarray
(i, j). For each subarray, we calculate its sum and check if removing it makes the remaining sum divisible byp. - Track Minimum Length: We track the length of the smallest subarray that can be removed and update the result accordingly.
- Final Check: If no subarray can make the remaining sum divisible by
p, we return-1.
๐ Time Complexity:
- O(nยณ) because we calculate the sum of every possible subarray in a nested loop, making this approach very inefficient for larger arrays.
Feel free to experiment with both solutions and compare their performance! ๐
Time Complexity:
- The brute force solution would involve checking all subarrays, leading to a time complexity of O(nยฒ), which can be inefficient when
n(length ofnums) is large.
โก Optimized Solution (Using Hash Maps)
The optimized approach leverages prefix sums and a hash map to track remainders of the prefix sums modulo p. This allows us to find the smallest subarray that we can remove efficiently.
Key Insights:
- Total Sum Modulo
p: We calculate the remainder of the total sum modulop. If the remainder is0, no subarray needs to be removed. - Prefix Sums and Hash Map: We compute the prefix sums while iterating over the array. The goal is to find subarrays that, when removed, leave the remaining elements divisible by
p. - Target Calculation: For each prefix sum, we calculate a target remainder that needs to be removed to make the remaining sum divisible by
p.
๐ Optimized Python Code
class Solution:
def minSubarray(self, nums: List[int], p: int) -> int:
total_sum = sum(nums)
remainder = total_sum % p
# If total sum is divisible by p, no removal needed
if remainder == 0:
return 0
n = len(nums)
min_len = n
prefix_sum = 0
prefix_map = {0: -1} # To store the prefix sums and their indexes
for i, num in enumerate(nums):
prefix_sum = (prefix_sum + num) % p
target = (prefix_sum - remainder) % p
# Check if we can remove a subarray to make the remaining sum divisible by p
if target in prefix_map:
min_len = min(min_len, i - prefix_map[target])
# Store the current prefix sum in the map
prefix_map[prefix_sum] = i
# Return -1 if no valid subarray is found
return min_len if min_len < n else -1
๐ Explanation of the Code:
- Calculate the total sum: We compute the sum of all elements in the array and find the remainder when divided by
p. - Early Exit: If the remainder is
0, we donโt need to remove any elements, so we return0. - Prefix Sum Calculation: As we iterate through the array, we compute the prefix sum modulo
pand store it in a hash map with the corresponding index. - Find the Target: For each prefix sum, we calculate the target remainder that needs to be removed. If this target exists in the hash map, it means we can remove a subarray and update the minimum length.
- Final Check: If a valid subarray is found, we return the minimum length. Otherwise, return
-1if no subarray can make the sum divisible byp.
๐ Time Complexity:
- O(n) where
nis the length of the array. We only traverse the array once and perform constant-time lookups and insertions in the hash map.
๐ฏ Conclusion
- The optimized approach gives us a linear-time solution using a prefix sum and hash map, which is much more efficient than the brute force approach.
- This algorithm is particularly useful when working with large arrays, as it ensures we donโt have to check every subarray manually.
- If the remainder after dividing the sum by
pis non-zero, we efficiently track possible subarrays that can be removed using modular arithmetic.
Hope this helps you understand how to tackle problems involving divisible sums and subarray removals! ๐ Keep coding!