又是没有 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) { int n = derived.length; int first = 1 ; int pre = 1 ; for (int i = 0 ; i < n; i++) { if (derived[i] == 1 ) { pre = 1 - pre; } else { 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; } else { 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 { 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); } } }