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;
}
}
|