Given an array of positive integers nums
, remove the smallest subarray (possibly empty) such that the sum of the remaining elements is divisible by p
. It is not allowed to remove the whole array.
Return the length of the smallest subarray that you need to remove, or -1
if it's impossible.
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 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
题目链接:https://leetcode.com/problems/make-sum-divisible-by-p/
题目大意:删除一个长度最短的子数组使得剩余数字和是p的倍数
题目分析:预处理后缀和模值,并用map记录,对每个前缀和模值找其后最近的与其相加为p的后缀模值
58ms,时间击败59.31%
class Solution {
public int minSubarray(int[] nums, int p) {
int ans = Integer.MAX_VALUE, n = nums.length, sufmod = 0;
Map<Integer, List<Integer>> pos = new HashMap<>();
for (int i = n - 1; i >= 0; i--) {
sufmod = (sufmod + nums[i]) % p;
if (sufmod == 0) {
ans = i;
}
if (!pos.containsKey(sufmod)) {
pos.put(sufmod, new ArrayList<>());
}
pos.get(sufmod).add(i);
}
int premod = 0;
for (int i = 0; i < n; i++) {
premod = (premod + nums[i]) % p;
if (premod == 0) {
ans = Math.min(ans, n - i - 1);
}
if (pos.containsKey(p - premod)) {
List<Integer> rpos = pos.get(p - premod);
int sz = rpos.size();
for (int j = sz - 1; j >= 0; j--) {
if (rpos.get(j) > i) {
ans = Math.min(ans, rpos.get(j) - i - 1);
break;
}
}
}
}
if (ans == Integer.MAX_VALUE) {
return -1;
}
return ans;
}
}