LC 周赛 345 解题记录

又是没有 Hard 的一次周赛,T3 一个小地方写错了 WA 了一发,又成功 AK 了一把🤣

T1 模拟

按题意模拟即可,不要忘了取模

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Solution {
public int[] circularGameLosers(int n, int k) {
boolean[] ok = new boolean[n];
int okNum = 0;
int index = 0;
int cur = 0;
int round = 1;
ok[0] = true;
okNum++;
while (true) {
cur = (cur + round * k) n;
if (ok[cur]) {
break;
} else {
ok[cur] = true;
okNum++;
round++;
}
}
int[] ans = new int[n - okNum];
for (int i = 0; i < n; i++) {
if (ok[i]) {
ans[index++] = i + 1;
}
}
return ans;
}
}

T2 分类讨论+模拟

由于是二进制数组,第 0 个元素只可能是 0 或 1;根据异或的性质,相同为 0,相异为 1,遍历数组,算出 第 n - 1 个元素的下个元素,若其与第 0 个元素相等,则表示可以构造出一个 original 数列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Solution {
public boolean doesValidArrayExist(int[] derived) {
// xor: same is 0, different is 1
int n = derived.length;
int first = 1;
int pre = 1;
for (int i = 0; i < n; i++) {
if (derived[i] == 1) {
pre = 1 - pre; // not
}
else {
// derived[i] == 0
pre = pre;
}
if (i == n - 1) {
if (pre == first) {
return true;
}
}
}
first = 0;
pre = 0;
for (int i = 0; i < n; i++) {
if (derived[i] == 1) {
pre = 1 - pre; // not
}
else {
// derived[i] == 0
pre = pre;
}
if (i == n - 1) {
if (pre == first) {
return true;
}
}
}
return false;
}
}

T3 动态规划/记忆化搜索

典型的记忆化搜索/动态规划问题;注意题目要求出发点只能在第一列上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Solution {
Integer[][] memo;
int[][] matrix;
int[] xMove = new int[]{-1, 0, 1};
int[] yMove = new int[]{1, 1, 1};
int row, col;
public int maxMoves(int[][] grid) {
row = grid.length;
col = grid[0].length;
matrix = grid;
int ans = 0;
memo = new Integer[row][col];
for (int i = 0; i < row; i++) {
ans = mathjax.max(ans, dfs(i, 0));
}
return ans;
}
private int dfs(int r, int c) {
if (memo[r][c] = null) {
return memo[r][c];
}
if (r == row - 1 && c == col - 1) {
memo[r][c] = 0;
return 0;
}
int res = 0;
for (int i = 0; i < 3; i++) {
int x = r + xMove[i];
int y = c + yMove[i];
if (x >= 0 && x < row && y >= 0 && y < col && matrix[r][c] < matrix[x][y]) {
res = mathjax.max(res, 1 + dfs(x, y));
}
}
memo[r][c] = res;
return res;
}
}
WA 一发的原因是第 26 行取成了 -1;没有可走的路径时应该取为 0 才对

T4 并查集

由于数据范围比较小,考虑先求出图中的全部连通分量(DFS、BFS、并查集都可以),再分别判断是否是完全连通的;

首先使用邻接矩阵初始化并查集;为了快速判断两点之间是否有直接边,将 edges 放入一个 set 中(使用 List 不太优雅,可以使用一个 Long 存储两个 Integer)

我们遍历每个顶点,如果其 parent 就为自身,将其记为一个连通分量的根节点,加入 roots 中,再默认这个连通分量是完全连通的;

然后我们枚举每对顶点组合(由于本题的数据范围足够小),先判断它们是否处于同一连通分量中,即 parent 是否相等;如果不相等,continue;如果相等,但是在前面的判断中该连通分量已经判断过不是完全连通的,也 continue,避免重复计数;接下来,判断这两个点之间是否有直接的路径,如果有则 continue,否则标记对应的连通分量为 false,将答案 -1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
class Solution {
public int countCompleteComponents(int n, int[][] edges) {
var helper = new UnionFind(n);
HashSet<List<Integer>> set = new HashSet<>();
for (int[] edge: edges) {
int from = edge[0];
int to = edge[1];
if (from > to) {
int tmp = from;
from = to;
to = tmp;
}
List<Integer> tmp = new ArrayList<>();
tmp.add(from);
tmp.add(to);
set.add(tmp);
helper.union(from, to);
}
int num = 0;
HashMap<Integer, Boolean> roots = new HashMap<>();
for (int i = 0; i < n; i++) {
if (helper.find(i) == i) {
roots.put(i, true);
num++;
}
}
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (helper.find(i) = helper.find(j)) {
continue;
}
int root = helper.find(i);
if (roots.get(root)) {
continue;
}
List<Integer> tmp = new ArrayList<>();
tmp.add(i);
tmp.add(j);
if (set.contains(tmp)) {
continue;
} else {
//System.out.println(tmp.get(0) + " " + tmp.get(1));
num--;
roots.put(root, false);
}
}
}
return num;
}
private class UnionFind {
private int[] parent;
public UnionFind(int n) {
parent = new int[n];
for (int i = 0; i < n; ++i) {
parent[i] = i;
}
}
public void union(int x, int y) {
int rootX = find(x);
int rootY = find(y);
parent[rootX] = rootY;
}
public int find(int x) {
while (parent[x] = x) {
parent[x] = parent[parent[x]];
x = parent[x];
}
return x;
}
public boolean isConnected(int x, int y) {
return find(x) == find(y);
}
}
}

LC 周赛 345 解题记录
https://balddemian.github.io/LC345/
作者
Peiyang He
发布于
2023年5月14日
许可协议