diff --git a/leetcode/leetcode-22/src/main/java/Solution2113.java b/leetcode/leetcode-22/src/main/java/Solution2113.java new file mode 100644 index 00000000..04a1665d --- /dev/null +++ b/leetcode/leetcode-22/src/main/java/Solution2113.java @@ -0,0 +1,42 @@ +import java.util.Arrays; + +public class Solution2113 { + public int[] elementInNums(int[] nums, int[][] queries) { + int n = nums.length; + int q = queries.length; + int[] ans = new int[q]; + Arrays.fill(ans, -1); + for (int i = 0; i < q; i++) { + int t = queries[i][0], idx = queries[i][1]; + t %= 2 * n; + if (t < n && idx < n - t) { + ans[i] = nums[t + idx]; + } else if (t> n && idx < t - n) { + ans[i] = nums[idx]; + } + } + return ans; + } +} +/* +2113ドル. 查询删除和添加元素后的数组 +https://leetcode.cn/problems/elements-in-array-after-removing-and-replacing-elements/description/ + +给你一个 下标从 0 开始 的数组 nums。一开始,在第 0 分钟,数组没有变化。此后每过一分钟,数组的 最左边 的元素将被移除,直到数组为空。然后,每过一分钟,数组的 尾部 将添加一个元素,添加的顺序和删除的顺序相同,直到数组被复原。此后上述操作无限循环进行。 +- 举个例子,如果 nums = [0, 1, 2],那么数组将按如下流程变化:[0,1,2] → [1,2] → [2] → [] → [0] → [0,1] → [0,1,2] → [1,2] → [2] → [] → [0] → [0,1] → [0,1,2] → ... +然后给你一个长度为 n 的二维数组 queries,其中 queries[j] = [timej, indexj],表示第 j 个查询。第 j 个查询的答案定义如下: +- 如果在时刻 timej,indexj < nums.length,那么答案是此时的 nums[indexj]; +- 如果在时刻 timej,indexj>= nums.length,那么答案是 -1。 +请返回一个长度为 n 的整数数组 ans,其中 ans[j] 为第 j 个查询的答案。 +提示: +1 <= nums.length <= 100 +0 <= nums[i] <= 100 +n == queries.length +1 <= n <= 10^5 +queries[j].length == 2 +0 <= timej <= 10^5 +0 <= indexj < nums.length + + +时间复杂度 O(q)。 + */ \ No newline at end of file diff --git a/leetcode/leetcode-22/src/main/java/Solution2123.java b/leetcode/leetcode-22/src/main/java/Solution2123.java new file mode 100644 index 00000000..9ba13b4d --- /dev/null +++ b/leetcode/leetcode-22/src/main/java/Solution2123.java @@ -0,0 +1,127 @@ +import java.util.ArrayDeque; +import java.util.Arrays; +import java.util.Queue; + +public class Solution2123 { + public int minimumOperations(int[][] grid) { + int m = grid.length; + int n = grid[0].length; + int id = 1; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (grid[i][j] == 1) grid[i][j] = id++; + } + } + + int S = id++; + int T = id++; + MaxFlow maxFlow = new MaxFlow(S, T); + + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (grid[i][j] == 0) continue; + int x = grid[i][j]; + if (i - 1>= 0 && grid[i - 1][j]> 0) { + int y = grid[i - 1][j]; + // 偶数到奇数连 1 + if ((i + j) % 2 == 0) maxFlow.add(x, y, 1); + else maxFlow.add(y, x, 1); + } + if (j - 1>= 0 && grid[i][j - 1]> 0) { + int y = grid[i][j - 1]; + // 偶数到奇数连 1 + if ((i + j) % 2 == 0) maxFlow.add(x, y, 1); + else maxFlow.add(y, x, 1); + } + if ((i + j) % 2 == 0) maxFlow.add(S, x, 1); + else maxFlow.add(x, T, 1); + } + } + return (int) maxFlow.maxflow(); + } + + static class MaxFlow { + int inf = 1 << 29, N = 100010, M = 600010; + int[] head = new int[N], ver = new int[M], edge = new int[M], Next = new int[M], d = new int[N]; + int n, m, s, t, tot; + long maxflow; + Queue q; + + public MaxFlow(int s, int t) { + this.s = s; + this.t = t; + this.tot = 1; + } + + void add(int x, int y, int z) { + ver[++tot] = y; + edge[tot] = z; + Next[tot] = head[x]; + head[x] = tot; + + ver[++tot] = x; + edge[tot] = 0; + Next[tot] = head[y]; + head[y] = tot; + } + + boolean bfs() { // 在残量网络上构造分层图 + Arrays.fill(d, 0); + while (!q.isEmpty()) q.remove(); + q.add(s); + d[s] = 1; + while (!q.isEmpty()) { + int x = q.remove(); + for (int i = head[x]; i != 0; i = Next[i]) { + if (edge[i] != 0 && d[ver[i]] == 0) { + q.add(ver[i]); + d[ver[i]] = d[x] + 1; + if (ver[i] == t) return true; + } + } + } + return false; + } + + int dinic(int x, int flow) { // 在当前分层图上增广 + if (x == t) return flow; + int rest = flow, k; + for (int i = head[x]; i != 0 && rest != 0; i = Next[i]) { + if (edge[i] != 0 && d[ver[i]] == d[x] + 1) { + k = dinic(ver[i], Math.min(rest, edge[i])); + if (k == 0) d[ver[i]] = 0; // 剪枝,去掉增广完毕的点 + edge[i] -= k; + edge[i ^ 1] += k; + rest -= k; + } + } + return flow - rest; + } + + long maxflow() { + q = new ArrayDeque(); + long flow; + while (bfs()) { + while ((flow = dinic(s, inf)) != 0) maxflow += flow; + } + return maxflow; + } + } +} +/* +2123ドル. 使矩阵中的 1 互不相邻的最小操作数 +https://leetcode.cn/problems/minimum-operations-to-remove-adjacent-ones-in-matrix/description/ + +给你一个 下标从 0 开始 的矩阵 grid。每次操作,你可以把 grid 中的 一个 1 变成 0 。 +如果一个矩阵中,没有 1 与其它的 1 四连通(也就是说所有 1 在上下左右四个方向上不能与其他 1 相邻),那么该矩阵就是 完全独立 的。 +请返回让 grid 成为 完全独立 的矩阵的 最小操作数。 +提示: +m == grid.length +n == grid[i].length +1 <= m, n <= 300 +grid[i][j] 是 0 或者 1. + +二分图最大匹配,由于 O(nm) 会 TLE。 +该用 Dinic 最大流来求。 +时间复杂度 O(sqrt(n) * m)。 + */ \ No newline at end of file diff --git a/leetcode/leetcode-22/src/test/java/Solution2113Tests.java b/leetcode/leetcode-22/src/test/java/Solution2113Tests.java new file mode 100644 index 00000000..bae672b6 --- /dev/null +++ b/leetcode/leetcode-22/src/test/java/Solution2113Tests.java @@ -0,0 +1,10 @@ +import org.junit.jupiter.api.Test; + +public class Solution2113Tests { + private final Solution2113 solution2113 = new Solution2113(); + + @Test + public void example1() { + + } +} \ No newline at end of file diff --git a/leetcode/leetcode-27/src/main/java/Solution2604.java b/leetcode/leetcode-27/src/main/java/Solution2604.java new file mode 100644 index 00000000..081080fd --- /dev/null +++ b/leetcode/leetcode-27/src/main/java/Solution2604.java @@ -0,0 +1,58 @@ +import java.util.Arrays; + +public class Solution2604 { + private int[] hens, grains; + private int n, m; + + public int minimumTime(int[] hens, int[] grains) { + Arrays.sort(hens); + Arrays.sort(grains); + this.hens = hens; + this.grains = grains; + n = hens.length; + m = grains.length; + + int left = 0; + int right = hens[n - 1] + grains[m - 1]; + while (left < right) { + int mid = left + (right - left) / 2; + // 边界二分 F, F,..., F, [T, T,..., T] + // ----------------------^ + if (checkMid(mid)) { + right = mid; + } else { + left = mid + 1; + } + } + return left; + } + + private boolean checkMid(int time) { + int i = 0, j = 0; + while (i < n && j < m) { + int left = hens[i], right = hens[i]; + while (j < m) { + left = Math.min(left, grains[j]); + right = Math.max(right, grains[j]); + if (Math.min(hens[i] - left, right - hens[i]) + right - left> time) break; + j++; + } + i++; + } + return j == m; + } +} +/* +2604ドル. 吃掉所有谷子的最短时间 +https://leetcode.cn/problems/minimum-time-to-eat-all-grains/description/ + +一条线上有 n 只母鸡和 m 颗谷子。给定两个整数数组 hens 和 grains ,它们的大小分别为 n 和 m ,表示母鸡和谷子的初始位置。 +如果一只母鸡和一颗谷子在同一个位置,那么这只母鸡可以吃掉这颗谷子。吃掉一颗谷子的时间可以忽略不计。一只母鸡也可以吃掉多颗谷子。 +在 1 秒钟内,一只母鸡可以向左或向右移动 1 个单位。母鸡可以同时且独立地移动。 +如果母鸡行动得当,返回吃掉所有谷子的 最短 时间。 +提示: +1 <= hens.length, grains.length <= 2*10^4 +0 <= hens[i], grains[j] <= 10^9 + +二分答案。 + */ \ No newline at end of file diff --git a/leetcode/leetcode-27/src/main/java/Solution2664.java b/leetcode/leetcode-27/src/main/java/Solution2664.java new file mode 100644 index 00000000..e74ef20b --- /dev/null +++ b/leetcode/leetcode-27/src/main/java/Solution2664.java @@ -0,0 +1,2 @@ +public class Solution2664 { +} diff --git a/leetcode/leetcode-30/src/main/java/Solution2907.java b/leetcode/leetcode-30/src/main/java/Solution2907.java new file mode 100644 index 00000000..7bece574 --- /dev/null +++ b/leetcode/leetcode-30/src/main/java/Solution2907.java @@ -0,0 +1,2 @@ +public class Solution2907 { +} diff --git a/leetcode/leetcode-30/src/main/java/Solution2921.java b/leetcode/leetcode-30/src/main/java/Solution2921.java new file mode 100644 index 00000000..f0417fa7 --- /dev/null +++ b/leetcode/leetcode-30/src/main/java/Solution2921.java @@ -0,0 +1,2 @@ +public class Solution2921 { +} diff --git a/leetcode/leetcode-31/src/main/java/Solution3073.java b/leetcode/leetcode-31/src/main/java/Solution3073.java new file mode 100644 index 00000000..2ec8327a --- /dev/null +++ b/leetcode/leetcode-31/src/main/java/Solution3073.java @@ -0,0 +1,2 @@ +public class Solution3073 { +}

AltStyle によって変換されたページ (->オリジナル) /