Problem

Explanation
We are given an array `[x_0,x_1,x_2,\dots ,x_{n-1}] ,` and a positive integer `p`. Let `S` represent the total sum of the array and `R` the total remainder, defined as `R = S \bmod p.` Our goal is to remove one contiguous subarray `[x_i,\dots ,x_j]` such that the remaining sum is divisible by `p`: ``(S-(x_i + \cdots + x_j)) \bmod p = 0.``This condition is equivalent to `` (x_i + \cdots + x_j) \bmod p = R.`` So the task reduces to finding the shortest subarray whose sum modulo `p` equals `R`.
To efficiently compute subarray sums, we use prefix sums modulo `p`. Define `P_k` as the remainder of the sum of all elements from the beginning of the array up to index `k`:
``P_{k} = (x_0 + \dots + x_{k}) \bmod p``
To prevent integer overflow when dealing with large values, we can compute these incrementally using `P_k = (P_{k-1} + x_k)%p`. This allows us to maintain the running remainder without needing to store the actual cumulative sum of the array.
For any subarray `[x_i,\dots ,x_j]` its sum modulo `p` can be computed using prefix sums: ``(x_i + \cdots + x_j) \bmod p = ((x_0 + \cdots + x_j) - (x_0 + \cdots + x_{i-1})) \bmod p = (P_j - P_{i-1}) \bmod p ``
We want this value to equal `R`, so we write: ``(P_j - P_{i-1} +p) \bmod p = R.``
Rearranging the equation gives: ``P_{i-1} = (P_j - R + p) \bmod p.``
The addition of `p` ensures the value is non-negative before applying modulo. In C++, the ##%## operator computes a remainder, not a true mathematical modulo, and can return negative values when the left operand is negative (for example, ##-1 % 7 = -1## when mathematically `-1 \bmod 7 = 6`).
Thus, for each `P_j`, we need to check if the required `P_{i-1}` has been encountered previously. To perform this check in `O(1)` time, we store the values in a hash map where the key is the prefix sums modulo and the value is the index of its most recent occurence. The algorithm follows these steps:
- Initialize a hash map with the entry ##{0, -1}##. This handles the case where `P_{-1}=0`, allowing us to identify and handle subarrays that begin at index 0.
- Iterate through the array, updating the current prefix sum modulo `p` at each step `j`.
- If `P_{i-1}` exists in the map, calculate the length of the candidate subarray `j - map[P_{i-1}]` and update the minimum length found so far
- Update map with current index `j` for the key value `P_j` to ensure we will be using the most recent index for future checks to minimize distance.
- If the minimum length remains equal to the original array length after a full iteration, conclude that no such subarray exists and return `-1`.
Solution
#include <vector>
#include <unordered_map>
#include <algorithm>
class Solution {
public:
int minSubarray(vector<int>& nums, int p) {
int n = nums.size();
int R = 0;
for(int x: nums) R = (R + x) % p;
if(R == 0) return 0;
std::unordered_map<int, int> prefix = {{0, -1}};
int P_curr = 0;
int ans = n;
for(int j=0; j<n; j++) {
P_curr = (P_curr + nums[j]) % p;
int P_prev = (P_curr - R + p)%p;
if(prefix.count(P_prev)) {
ans = std::min(ans, j - prefix[P_prev]);
}
prefix[P_curr] = j;
}
if (ans == n) return -1;
return ans;
}
};
'Computer Science > Problem Solving' 카테고리의 다른 글
| [LeetCode] 493. Reverse Pairs (0) | 2026.04.08 |
|---|---|
| [LeetCode] 2681. Power of Heroes (0) | 2026.01.21 |
| [LeetCode] 1354. Construct Target Array with Multiple Sums (0) | 2025.12.31 |
| [LeetCode] 84. Largest Rectangle in Histogram (0) | 2025.12.26 |
| [LeetCode] 389. Find the Difference (0) | 2025.12.19 |