题目
3.1590. 使数组和能被 P 整除
4.1591. 奇怪的打印机 II
思路与算法
- 第三题前缀和衍生题目,需要一个同余定理的前缀知识,不多bb了,剩下就是前缀和加一些简单的处理技巧。
- 第四题图着色问题不再赘述见代码
代码实现
3.1590. 使数组和能被 P 整除
class Solution {
public int minSubarray(int[] nums, int p) {
int n = nums.length;
Map<Integer, Integer> hashmap = new HashMap<>();
hashmap.put(0,0);
int[] presum = new int[n+1];
int sum = 0;
int ans = Integer.MAX_VALUE;
for (int i = 0; i < n ; i++){
int now = nums[i];
sum = (int)((long)(sum+now)%p);
presum[i+1] = (int)((long)(presum[i]+now)%p);
}
int res = sum%p;
for (int i = 1; i<=n ;i++){
int cur = presum[i];
hashmap.put(cur,i);
int target = (int)((long)(cur-res+p)%p);
if (hashmap.containsKey(target)){
ans = Math.min(ans, i-hashmap.get(target));
}
}
if (ans == Integer.MAX_VALUE || ans == n)return -1;
return ans;
}
}
4.1591. 奇怪的打印机 II
class Solution {
class Node {
int left;
int up;
int right;
int bottom;
Node(int a, int b, int c, int d) {
left = a;
up = b;
right = c;
bottom = d;
}
}
public boolean isPrintable(int[][] targetGrid) {
Map<Integer, Node> colorPos = new HashMap<>();
// 找到每种color的左上右下角
int m = targetGrid.length;
int n = targetGrid[0].length;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
int color = targetGrid[i][j];
if (colorPos.containsKey(color)) {
Node node = colorPos.get(color);
node.bottom = Math.max(node.bottom, i);
node.up = Math.min(node.up, i);
node.left = Math.min(node.left, j);
node.right = Math.max(node.right, j);
} else {
colorPos.put(color, new Node(j, i, j, i));
}
}
}
Set<Integer> colors = new HashSet<>(colorPos.keySet());
while (!colors.isEmpty()) {
// 找到能删除的颜色,删除该颜色
Set<Integer> deletion = new HashSet<>();
// 边forloop 一个set边删除,会有ConcurrentModificationException
for (int c : colors) {
if (isOneColor(targetGrid, colorPos.get(c), c)) {
deletion.add(c);
}
}
if (deletion.isEmpty()) {
return false;
}
colors.removeAll(deletion);
}
return true;
}
private boolean isOneColor(int[][] targetGrid, Node boundary, int color) {
// 检查边界长方形能不能完全删除
for (int i = boundary.up; i <= boundary.bottom; i++) {
for (int j = boundary.left; j <= boundary.right; j++) {
if (targetGrid[i][j] > 0 && targetGrid[i][j] != color) {
return false;
}
}
}
// 把这种color清空为0
for (int i = boundary.up; i <= boundary.bottom; i++) {
for (int j = boundary.left; j <= boundary.right; j++) {
targetGrid[i][j] = 0;
}
}
return true;
}
}