Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 1b7c52a

Browse files
committed
第456场周赛T1~T4 (4)
1 parent 9690e3f commit 1b7c52a

File tree

8 files changed

+440
-0
lines changed

8 files changed

+440
-0
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import java.util.ArrayList;
2+
import java.util.HashSet;
3+
import java.util.List;
4+
import java.util.Set;
5+
6+
public class Solution3597 {
7+
public List<String> partitionString(String s) {
8+
int n = s.length();
9+
Set<String> set = new HashSet<>();
10+
List<String> ans = new ArrayList<>();
11+
int i = 0;
12+
while (i < n) {
13+
for (int j = i + 1; j <= n; j++) {
14+
String sub = s.substring(i, j);
15+
if (!set.contains(sub)) {
16+
set.add(sub);
17+
ans.add(sub);
18+
i = j - 1;
19+
break;
20+
}
21+
}
22+
i++;
23+
}
24+
return ans;
25+
}
26+
}
27+
/*
28+
3597. 分割字符串
29+
https://leetcode.cn/problems/partition-string/description/
30+
31+
第 456 场周赛 T1。
32+
33+
给你一个字符串 s,按照以下步骤将其分割为 互不相同的段 :
34+
从下标 0 开始构建一个段。
35+
逐字符扩展当前段,直到该段之前未曾出现过。
36+
只要当前段是唯一的,就将其加入段列表,标记为已经出现过,并从下一个下标开始构建新的段。
37+
重复上述步骤,直到处理完整个字符串 s。
38+
返回字符串数组 segments,其中 segments[i] 表示创建的第 i 段。
39+
提示:
40+
1 <= s.length <= 10^5
41+
s 仅包含小写英文字母。
42+
43+
哈希表模拟。
44+
时间复杂度 O(n * sqrt(n))
45+
*/
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
public class Solution3598 {
2+
public int[] longestCommonPrefix(String[] words) {
3+
int n = words.length;
4+
if (n == 1) return new int[1];
5+
if (n == 2) return new int[2];
6+
7+
int[] pre = new int[n - 1];
8+
for (int i = 0; i < n - 1; i++) {
9+
pre[i] = getLcpLen(words[i], words[i + 1]);
10+
}
11+
12+
int[] L = new int[n - 1];
13+
L[0] = pre[0];
14+
for (int i = 1; i < n - 1; i++) {
15+
L[i] = Math.max(L[i - 1], pre[i]);
16+
}
17+
18+
int[] R = new int[n - 1];
19+
R[n - 2] = pre[n - 2];
20+
for (int i = n - 3; i >= 0; i--) {
21+
R[i] = Math.max(R[i + 1], pre[i]);
22+
}
23+
24+
int[] ans = new int[n];
25+
for (int i = 0; i < n; i++) {
26+
if (i == 0) {
27+
ans[i] = R[1];
28+
} else if (i == n - 1) {
29+
ans[i] = L[n - 3];
30+
} else {
31+
int max1 = i - 2 >= 0 ? L[i - 2] : 0;
32+
int max2 = i + 1 <= n - 2 ? R[i + 1] : 0;
33+
int max3 = getLcpLen(words[i - 1], words[i + 1]);
34+
ans[i] = Math.max(Math.max(max1, max2), max3);
35+
}
36+
}
37+
return ans;
38+
}
39+
40+
private int getLcpLen(String str1, String str2) {
41+
int minLen = Math.min(str1.length(), str2.length());
42+
for (int i = 0; i < minLen; i++) {
43+
if (str1.charAt(i) != str2.charAt(i)) {
44+
return i;
45+
}
46+
}
47+
return minLen;
48+
}
49+
}
50+
/*
51+
3598. 相邻字符串之间的最长公共前缀
52+
https://leetcode.cn/problems/longest-common-prefix-between-adjacent-strings-after-removals/description/
53+
54+
第 456 场周赛 T2。
55+
56+
给你一个字符串数组 words,对于范围 [0, words.length - 1] 内的每个下标 i,执行以下步骤:
57+
- 从 words 数组中移除下标 i 处的元素。
58+
- 计算修改后的数组中所有 相邻对 之间的 最长公共前缀 的长度。
59+
返回一个数组 answer,其中 answer[i] 是移除下标 i 后,相邻对之间最长公共前缀的长度。如果 不存在 相邻对,或者 不存在 公共前缀,则 answer[i] 应为 0。
60+
字符串的前缀是从字符串的开头开始延伸到任意位置的子字符串。
61+
提示:
62+
1 <= words.length <= 10^5
63+
1 <= words[i].length <= 10^4
64+
words[i] 仅由小写英文字母组成。
65+
words[i] 的长度总和不超过 10^5。
66+
67+
前后缀分解。
68+
时间复杂度 O(L)。其中 L 为 words[i] 的长度总和。
69+
*/
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
public class Solution3599 {
2+
static class V1 {
3+
private int n, k;
4+
private int[] pre_xor;
5+
6+
public int minXor(int[] nums, int k) {
7+
this.n = nums.length;
8+
this.k = k;
9+
pre_xor = new int[n + 1];
10+
for (int i = 1; i <= n; i++) {
11+
pre_xor[i] = pre_xor[i - 1] ^ nums[i - 1];
12+
}
13+
14+
int left = 0;
15+
int right = 1 << 30;
16+
while (left < right) {
17+
int mid = left + (right - left) / 2;
18+
// 边界二分 F, F,..., F, [T, T,..., T]
19+
// ----------------------^
20+
if (check(mid)) {
21+
right = mid;
22+
} else {
23+
left = mid + 1;
24+
}
25+
}
26+
return left;
27+
}
28+
29+
private boolean check(int mid) {
30+
boolean[][] dp = new boolean[n + 1][k + 1];
31+
dp[0][0] = true;
32+
33+
for (int j = 1; j <= k; j++) {
34+
for (int i = j; i <= n; i++) {
35+
for (int p = j - 1; p < i; p++) {
36+
if (dp[p][j - 1]) {
37+
int xor_val = pre_xor[i] ^ pre_xor[p];
38+
if (xor_val <= mid) {
39+
dp[i][j] = true;
40+
break; // 找到一种分割方式即可,跳出内层循环
41+
}
42+
}
43+
}
44+
}
45+
}
46+
return dp[n][k];
47+
}
48+
}
49+
}
50+
/*
51+
3599. 划分数组得到最小 XOR
52+
https://leetcode.cn/problems/partition-array-to-minimize-xor/description/
53+
54+
第 456 场周赛 T3。
55+
56+
给你一个整数数组 nums 和一个整数 k。
57+
你的任务是将 nums 分成 k 个非空的 子数组 。对每个子数组,计算其所有元素的按位 XOR 值。
58+
返回这 k 个子数组中 最大 XOR 的 最小值 。
59+
子数组 是数组中连续的 非空 元素序列。
60+
提示:
61+
1 <= nums.length <= 250
62+
1 <= nums[i] <= 10^9
63+
1 <= k <= n
64+
65+
二分答案 + 划分型 DP。
66+
或者直接划分型 DP。
67+
时间复杂度 O(logU * n^3)。上界大概是 O(30 * 250^3) = O(468,750,000)
68+
*/
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import java.util.ArrayList;
2+
import java.util.List;
3+
4+
public class Solution3600 {
5+
private int n, k;
6+
private List<int[]> mustEdges, optionalEdges;
7+
8+
public int maxStability(int n, int[][] edges, int k) {
9+
this.n = n;
10+
this.k = k;
11+
mustEdges = new ArrayList<>();
12+
optionalEdges = new ArrayList<>();
13+
for (int[] edge : edges) {
14+
if (edge[3] == 1) {
15+
mustEdges.add(edge);
16+
} else {
17+
optionalEdges.add(edge);
18+
}
19+
}
20+
21+
int left = 0;
22+
int right = (int) 2e5;
23+
while (left < right) {
24+
int mid = left + (right - left) / 2;
25+
// 边界二分 F, F,..., F, [T, T,..., T]
26+
// ----------------------^
27+
if (!check(mid)) {
28+
right = mid;
29+
} else {
30+
left = mid + 1;
31+
}
32+
}
33+
return left - 1;
34+
}
35+
36+
private boolean check(int X) {
37+
DSU uf = new DSU(n);
38+
39+
for (int[] edge : mustEdges) {
40+
int u = edge[0], v = edge[1], s = edge[2];
41+
if (s < X) {
42+
return false;
43+
}
44+
int ru = uf.find(u);
45+
int rv = uf.find(v);
46+
if (ru != rv) {
47+
uf.union(u, v);
48+
} else {
49+
return false;
50+
}
51+
}
52+
53+
int upgrades = 0;
54+
for (int[] edge : optionalEdges) {
55+
int u = edge[0], v = edge[1], s = edge[2];
56+
if (s >= X) {
57+
int ru = uf.find(u);
58+
int rv = uf.find(v);
59+
if (ru != rv) {
60+
uf.union(u, v);
61+
}
62+
}
63+
}
64+
65+
for (int[] edge : optionalEdges) {
66+
int u = edge[0], v = edge[1], s = edge[2];
67+
if (s < X && 2 * s >= X) {
68+
int ru = uf.find(u);
69+
int rv = uf.find(v);
70+
if (ru != rv) {
71+
uf.union(u, v);
72+
upgrades++;
73+
if (upgrades > k) {
74+
break;
75+
}
76+
}
77+
}
78+
}
79+
80+
return uf.sz == 1 && upgrades <= k;
81+
}
82+
83+
static class DSU {
84+
int[] fa;
85+
int sz;
86+
87+
public DSU(int n) {
88+
fa = new int[n];
89+
for (int i = 0; i < n; i++) fa[i] = i;
90+
sz = n;
91+
}
92+
93+
int find(int x) { // 查找
94+
return x == fa[x] ? fa[x] : (fa[x] = find(fa[x]));
95+
}
96+
97+
void union(int p, int q) { // 合并
98+
p = find(p);
99+
q = find(q);
100+
if (p == q) return;
101+
fa[q] = p;
102+
sz--;
103+
}
104+
}
105+
}
106+
/*
107+
3600. 升级后最大生成树稳定性
108+
https://leetcode.cn/problems/maximize-spanning-tree-stability-with-upgrades/description/
109+
110+
第 456 场周赛 T4。
111+
112+
给你一个整数 n,表示编号从 0 到 n - 1 的 n 个节点,以及一个 edges 列表,其中 edges[i] = [ui, vi, si, musti]:
113+
- ui 和 vi 表示节点 ui 和 vi 之间的一条无向边。
114+
- si 是该边的强度。
115+
- musti 是一个整数(0 或 1)。如果 musti == 1,则该边 必须 包含在生成树中,且 不能升级 。
116+
你还有一个整数 k,表示你可以执行的最多 升级 次数。每次升级会使边的强度 翻倍 ,且每条可升级边(即 musti == 0)最多只能升级一次。
117+
一个生成树的 稳定性 定义为其中所有边的 最小 强度。
118+
返回任何有效生成树可能达到的 最大 稳定性。如果无法连接所有节点,返回 -1。
119+
注意: 图的一个 生成树(spanning tree)是该图中边的一个子集,它满足以下条件:
120+
- 将所有节点连接在一起(即图是 连通的 )。
121+
- 不 形成任何环。
122+
- 包含 恰好 n - 1 条边,其中 n 是图中节点的数量。
123+
提示:
124+
2 <= n <= 10^5
125+
1 <= edges.length <= 10^5
126+
edges[i] = [ui, vi, si, musti]
127+
0 <= ui, vi < n
128+
ui != vi
129+
1 <= si <= 10^5
130+
musti 是 0 或 1。
131+
0 <= k <= n
132+
没有重复的边。
133+
134+
二分答案 + 并查集。
135+
时间复杂度 O((n+m)lognlogU)
136+
rating 2239 (clist.by)
137+
*/
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
import java.util.List;
5+
6+
public class Solution3597Tests {
7+
private final Solution3597 solution3597 = new Solution3597();
8+
9+
@Test
10+
public void example1() {
11+
String s = "abbccccd";
12+
List<String> expected = List.of("a", "b", "bc", "c", "cc", "d");
13+
Assertions.assertEquals(expected, solution3597.partitionString(s));
14+
}
15+
16+
@Test
17+
public void example2() {
18+
String s = "aaaa";
19+
List<String> expected = List.of("a", "aa");
20+
Assertions.assertEquals(expected, solution3597.partitionString(s));
21+
}
22+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
public class Solution3598Tests {
5+
private final Solution3598 solution3598 = new Solution3598();
6+
7+
@Test
8+
public void example1() {
9+
String[] words = {"jump", "run", "run", "jump", "run"};
10+
int[] expected = {3, 0, 0, 3, 3};
11+
Assertions.assertArrayEquals(expected, solution3598.longestCommonPrefix(words));
12+
}
13+
14+
@Test
15+
public void example2() {
16+
String[] words = {"dog", "racer", "car"};
17+
int[] expected = {0, 0, 0};
18+
Assertions.assertArrayEquals(expected, solution3598.longestCommonPrefix(words));
19+
}
20+
21+
// 补充用例
22+
@Test
23+
public void example3() {
24+
// https://leetcode.cn/problems/longest-common-prefix-between-adjacent-strings-after-removals/submissions/639893891/
25+
String[] words = {"cdbff"};
26+
int[] expected = {0};
27+
Assertions.assertArrayEquals(expected, solution3598.longestCommonPrefix(words));
28+
}
29+
30+
@Test
31+
public void example4() {
32+
String[] words = {"cdbff", "cdbff"};
33+
int[] expected = {0, 0};
34+
Assertions.assertArrayEquals(expected, solution3598.longestCommonPrefix(words));
35+
}
36+
}

0 commit comments

Comments
(0)

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