5499.重复至少 K 次且长度为 M 的模式
题目
给你一个正整数数组 arr,请你找出一个长度为 m 且在数组中至少重复 k 次的模式。
模式 是由一个或多个值组成的子数组(连续的子序列),连续 重复多次但 不重叠 。 模式由其长度和重复次数定义。
如果数组中存在至少重复 k 次且长度为 m 的模式,则返回 true ,否则返回 false 。
示例 1:
输入:arr = [1,2,4,4,4,4], m = 1, k = 3
输出:true
解释:模式 (4) 的长度为 1 ,且连续重复 4 次。注意,模式可以重复 k 次或更多次,但不能少于 k 次。
示例 2:
输入:arr = [1,2,1,2,1,1,1,3], m = 2, k = 2
输出:true
解释:模式 (1,2) 长度为 2 ,且连续重复 2 次。另一个符合题意的模式是 (2,1) ,同样重复 2 次。
示例 3:
输入:arr = [1,2,1,2,1,3], m = 2, k = 3
输出:false
解释:模式 (1,2) 长度为 2 ,但是只连续重复 2 次。不存在长度为 2 且至少重复 3 次的模式。
示例 4:
输入:arr = [1,2,3,1,2], m = 2, k = 2
输出:false
解释:模式 (1,2) 出现 2 次但并不连续,所以不能算作连续重复 2 次。
示例 5:
输入:arr = [2,2,2,2], m = 2, k = 3
输出:false
解释:长度为 2 的模式只有 (2,2) ,但是只连续重复 2 次。注意,不能计算重叠的重复次数。
提示:
2 <= arr.length <= 100
1 <= arr[i] <= 100
1 <= m <= 100
2 <= k <= 100
思路
暴力模拟
代码
class Solution {
public boolean containsPattern(int[] arr, int m, int k) {
boolean result = false;
int l = 0, r = m; //左闭右开
int co = 0;
for (; r < arr.length; l ++, r ++) {
boolean flag = true;
co = 0;
while (co < k - 1) {
int i = l, j = r + co * (r - l);
for (; i < r && j < arr.length; i++, j++) {
if(arr[i] == arr[j])
continue;
else {
flag = false;
break;
}
}
if(i != r)
flag = false;
if(!flag)
break;
co ++;
}
if(flag) {
result = true;
break;
}
}
return result;
}
}
5500.乘积为正数的最长子数组长度
题目
给你一个整数数组 nums ,请你求出乘积为正数的最长子数组的长度。
一个数组的子数组是由原数组中零个或者更多个连续数字组成的数组。
请你返回乘积为正数的最长子数组长度。
思路
将数组按0的位置分段,统计每一段中第一个和最后一个负数出现的位置以及这一段中负数的个数。由于一段中负数的个数不是奇数就是偶数,当负数个数是偶数时,这一整段都可以取,当负数个数为奇数时,将这一段按第一个出现负数的位置分为两段再按最后一个出现负数的位置分为两段,取4个数中的最大值。
19:49更新:
分两段就行,去掉前面一段剩下的和去掉后面一段剩下的。因为去掉右面一段剩下的一定大于等于被去掉的前面那一段,去掉前面一段剩下的一定大于等于被去掉的后面那一段。
感谢
代码
class Solution {
public int getMaxLen(int[] nums) {
int result = 0;
int fco = 0;//负数个数
int fpos = 0, lpos = 0;//第一次和最后一次出现负数的位置
int len = 0;//区间起始点
for (int i = 0; i < nums.length; i++) {
if(nums[i] == 0) {
if(fco % 2 == 0) {
result = Math.max(result, i - len);
} else {
result = Math.max(result, Math.max((fpos - len) , (i - fpos - 1)));
result = Math.max(result, Math.max((lpos - len) , (i - lpos - 1)));
}
fpos = 0;
lpos = 0;
fco = 0;
len = i + 1;
} else if(nums[i] < 0) {
if(fpos == 0 && fco == 0)
fpos = i;
fco ++;
lpos = i;
}
}
if(fco % 2 == 0) {
result = Math.max(result, nums.length - len);
} else {
result = Math.max(result, Math.max((fpos - len) , (nums.length - fpos - 1)));
result = Math.max(result, Math.max((lpos - len) , (nums.length - lpos - 1)));
}
return result;
}
}
21:34 补上第三题
5501.使陆地分离的最少天数
题目
给你一个由若干 0 和 1 组成的二维网格 grid ,其中 0 表示水,而 1 表示陆地。岛屿由水平方向或竖直方向上相邻的 1 (陆地)连接形成。
如果 恰好只有一座岛屿 ,则认为陆地是 连通的 ;否则,陆地就是 分离的 。
一天内,可以将任何单个陆地单元(1)更改为水单元(0)。
返回使陆地分离的最少天数。
思路
参考了这两位巨巨的思想:大雪菜和满嘴跑火车的小土匪
主要是要有将网格抽象成点的思想。
把网格抽象成点的话,图就成了无向图。题目就变成了:给一个无向图,问去掉多少个点能使无向图不连通。这就是网络流中求最小割。(ps:第一次补到第3题,原来周赛这么难的咩)
但是这是一个网格,实际上答案最多为2。举一个特例,假设网格全为1,去掉四个角上的1即为最优,只需要两次。
所以思路是:
- 首先利用并查集判断网格的连通性
- 如果连通块的个数为0或2以上,结果为0
- 如果连通块为1个,枚举每一个为1的格子将其置为0,重新计算一次连通性,如果连通块增加了,结果为1,反之结果为2。
代码
class Solution {
private int[] fa;
private int m, n;
public int minDays(int[][] grid) {
m = grid.length;
n = grid[0].length;
fa = new int[m * n];
int result = 0;
int count = m * n;
for (int i = 0; i < m * n; i++) {
fa[i] = i;
}
count = calIsland(grid, count);
if(count == 0 || count >= 2)//全为1或者有2个以上的连通块
result = 0;
else {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if(grid[i][j] == 1) {
grid[i][j] = 0;
for (int k = 0; k < m * n; k++) {
fa[k] = k;
}
int co = calIsland(grid, m * n);
if(co >= 2) {
result = 1;
break;
}
grid[i][j] = 1;
}
if(result == 1)
break;
}
}
if (result == 0)
result = 2;
}
return result;
}
private int getFather(int x) {
if(fa[x] == x) {
return x;
} else {
return fa[x] = getFather(fa[x]);
}
}
private void union(int x, int y) {
fa[y] = fa[x];
}
private int calIsland(int[][] grid, int count) {
m = grid.length;
n = grid[0].length;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if(grid[i][j] == 0)
count --;
else {
//向大的合并
if(i < m - 1 && grid[i + 1][j] == 1){
int x = getFather(i * n + j);
int y = getFather((i + 1) * n + j);
if(x != y) {
union(x, y);
count --;
}
}
if(j < n - 1 && grid[i][j + 1] == 1) {
int x = getFather(i * n + j);
int y = getFather(i * n + j + 1);
if(x != y) {
union(x, y);
count --;
}
}
}
}
}
return count;
}
}
还有一题有待补充。。。