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 3ea9d82

Browse files
committed
第434场周赛T1~T4 (4)
1 parent c53d177 commit 3ea9d82

File tree

8 files changed

+386
-0
lines changed

8 files changed

+386
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
public class Solution3432 {
2+
public int countPartitions(int[] nums) {
3+
int n = nums.length;
4+
int[] ps = new int[n + 1];
5+
for (int i = 0; i < n; i++) {
6+
ps[i + 1] = ps[i] + nums[i];
7+
}
8+
int ans = 0;
9+
for (int i = 0; i < n - 1; i++) {
10+
int L = ps[i + 1];
11+
int R = ps[n] - L;
12+
if (Math.floorMod(L - R, 2) == 0) {
13+
ans++;
14+
}
15+
}
16+
return ans;
17+
}
18+
}
19+
/*
20+
3432. 统计元素和差值为偶数的分区方案
21+
https://leetcode.cn/problems/count-partitions-with-even-sum-difference/description/
22+
23+
第 434 场周赛 T1。
24+
25+
给你一个长度为 n 的整数数组 nums 。
26+
分区 是指将数组按照下标 i (0 <= i < n - 1)划分成两个 非空 子数组,其中:
27+
- 左子数组包含区间 [0, i] 内的所有下标。
28+
- 右子数组包含区间 [i + 1, n - 1] 内的所有下标。
29+
对左子数组和右子数组先求元素 和 再做 差 ,统计并返回差值为 偶数 的 分区 方案数。
30+
提示:
31+
2 <= n == nums.length <= 100
32+
1 <= nums[i] <= 100
33+
34+
前缀和模拟。
35+
*/
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import java.util.List;
2+
3+
public class Solution3433 {
4+
public int[] countMentions(int numberOfUsers, List<List<String>> events) {
5+
// 按照时间戳从小到大排序,时间戳相同的,离线事件排在前面
6+
events.sort((o1, o2) -> {
7+
int t1 = Integer.parseInt(o1.get(1));
8+
int t2 = Integer.parseInt(o2.get(1));
9+
if (t1 == t2) {
10+
int priority1 = getPriority(o1.get(0));
11+
int priority2 = getPriority(o2.get(0));
12+
return Integer.compare(priority1, priority2);
13+
}
14+
return Integer.compare(t1, t2);
15+
});
16+
17+
int[] ans = new int[numberOfUsers];
18+
int[] onlineT = new int[numberOfUsers];
19+
for (List<String> e : events) {
20+
String msgType = e.get(0);
21+
int curT = Integer.parseInt(e.get(1));
22+
String mentions_string = e.get(2);
23+
if ("OFFLINE".equals(msgType)) {
24+
onlineT[Integer.parseInt(mentions_string)] = curT + 60;
25+
continue;
26+
}
27+
if ("ALL".equals(mentions_string)) {
28+
for (int i = 0; i < numberOfUsers; i++) {
29+
ans[i]++;
30+
}
31+
} else if ("HERE".equals(mentions_string)) {
32+
for (int i = 0; i < numberOfUsers; i++) {
33+
if (onlineT[i] <= curT) { // 在线
34+
ans[i]++;
35+
}
36+
}
37+
} else {
38+
for (String s : mentions_string.split(" ")) {
39+
int i = Integer.parseInt(s.substring(2));
40+
ans[i]++;
41+
}
42+
}
43+
}
44+
return ans;
45+
}
46+
47+
private int getPriority(String msgType) {
48+
return "OFFLINE".equals(msgType) ? 0 : 1;
49+
}
50+
}
51+
/*
52+
3433. 统计用户被提及情况
53+
https://leetcode.cn/problems/count-mentions-per-user/description/
54+
55+
第 434 场周赛 T2。
56+
57+
给你一个整数 numberOfUsers 表示用户总数,另有一个大小为 n x 3 的数组 events 。
58+
每个 events[i] 都属于下述两种类型之一:
59+
1.消息事件(Message Event):["MESSAGE", "timestampi", "mentions_stringi"]
60+
- 事件表示在 timestampi 时,一组用户被消息提及。
61+
- mentions_stringi 字符串包含下述标识符之一:
62+
- id<number>:其中 <number> 是一个区间 [0,numberOfUsers - 1] 内的整数。可以用单个空格分隔 多个 id ,并且 id 可能重复。此外,这种形式可以提及离线用户。
63+
- ALL:提及 所有 用户。
64+
- HERE:提及所有 在线 用户。
65+
2.离线事件(Offline Event):["OFFLINE", "timestampi", "idi"]
66+
- 事件表示用户 idi 在 timestampi 时变为离线状态 60 个单位时间。用户会在 timestampi + 60 时自动再次上线。
67+
返回数组 mentions ,其中 mentions[i] 表示 id 为 i 的用户在所有 MESSAGE 事件中被提及的次数。
68+
最初所有用户都处于在线状态,并且如果某个用户离线或者重新上线,其对应的状态变更将会在所有相同时间发生的消息事件之前进行处理和同步。
69+
注意 在单条消息中,同一个用户可能会被提及多次。每次提及都需要被 分别 统计。
70+
提示:
71+
1 <= numberOfUsers <= 100
72+
1 <= events.length <= 100
73+
events[i].length == 3
74+
events[i][0] 的值为 MESSAGE 或 OFFLINE 。
75+
1 <= int(events[i][1]) <= 105
76+
在任意 "MESSAGE" 事件中,以 id<number> 形式提及的用户数目介于 1 和 100 之间。
77+
0 <= <number> <= numberOfUsers - 1
78+
题目保证 OFFLINE 引用的用户 id 在事件发生时处于 在线 状态。
79+
80+
模拟。
81+
*/
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import java.util.Arrays;
2+
3+
public class Solution3434 {
4+
public int maxFrequency(int[] nums, int k) {
5+
int ans = 0;
6+
for (int target : Arrays.stream(nums).distinct().toArray()) {
7+
// f[i+1][0] 表示左,或者说 nums[i] 在被修改的子数组的左侧,此时只能统计等于 k 的元素个数。
8+
// f[i+1][1] 表示左+中,或者说 nums[i] 在被修改的子数组中,此时只能统计等于 target 的元素个数,这些数被修改成 k。注意不能统计子数组中的 k 的个数,因为子数组中的 k 会被修改成别的数。
9+
// f[i+1][2] 表示左+中+右,或者说 nums[i] 在被修改的子数组的右侧,此时只能统计等于 k 的元素个数。
10+
int f0 = 0, f1 = 0, f2 = 0;
11+
for (int x : nums) {
12+
f2 = Math.max(f2, f1) + (x == k ? 1 : 0);
13+
f1 = Math.max(f1, f0) + (x == target ? 1 : 0);
14+
f0 += (x == k ? 1 : 0);
15+
}
16+
ans = Math.max(ans, Math.max(f1, f2));
17+
}
18+
return ans;
19+
}
20+
}
21+
/*
22+
3434. 子数组操作后的最大频率
23+
https://leetcode.cn/problems/maximum-frequency-after-subarray-operation/description/
24+
25+
第 434 场周赛 T3。
26+
27+
给你一个长度为 n 的数组 nums ,同时给你一个整数 k 。
28+
你可以对 nums 执行以下操作 一次 :
29+
- 选择一个子数组 nums[i..j] ,其中 0 <= i <= j <= n - 1 。
30+
- 选择一个整数 x 并将 nums[i..j] 中 所有 元素都增加 x 。
31+
请你返回执行以上操作以后数组中 k 出现的 最大 频率。
32+
子数组 是一个数组中一段连续 非空 的元素序列。
33+
提示:
34+
1 <= n == nums.length <= 10^5
35+
1 <= nums[i] <= 50
36+
1 <= k <= 50
37+
38+
状态机 DP。
39+
时间复杂度 O(nU)。可以优化至 O(n)。
40+
rating 2093 (clist.by)
41+
*/
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import java.util.ArrayList;
2+
import java.util.Arrays;
3+
import java.util.HashSet;
4+
import java.util.List;
5+
import java.util.Set;
6+
7+
public class Solution3435 {
8+
private List<Integer>[] g;
9+
10+
public List<List<Integer>> supersequences(String[] words) {
11+
// 收集有哪些字母,同时建图
12+
int all = 0;
13+
g = new ArrayList[26];
14+
Arrays.setAll(g, e -> new ArrayList<>());
15+
for (String s : words) {
16+
int x = s.charAt(0) - 'a';
17+
int y = s.charAt(1) - 'a';
18+
all |= 1 << x;
19+
all |= 1 << y;
20+
g[x].add(y);
21+
}
22+
23+
Set<Integer> set = new HashSet<>();
24+
int minSize = Integer.MAX_VALUE;
25+
// 枚举 all 的所有子集 sub
26+
// sub 中的 0 表示字母的出现次数是 1.
27+
// sub 中的 1 表示字母的出现次数是 2.
28+
int sub = all;
29+
do {
30+
int size = Integer.bitCount(sub);
31+
// 剪枝:如果 size > minSize 就不需要判断了
32+
if (size <= minSize && !hasCycle(sub)) {
33+
if (size < minSize) {
34+
minSize = size;
35+
set.clear();
36+
}
37+
set.add(sub);
38+
}
39+
sub = (sub - 1) & all;
40+
} while (sub != all);
41+
42+
List<List<Integer>> ans = new ArrayList<>(set.size()); // 预分配空间
43+
for (int s : set) {
44+
List<Integer> cnt = new ArrayList<>(26); // 预分配空间
45+
for (int i = 0; i < 26; i++) {
46+
cnt.add((all >> i & 1) + (s >> i & 1));
47+
}
48+
ans.add(cnt);
49+
}
50+
return ans;
51+
}
52+
53+
private boolean hasCycle(int sub) {
54+
int[] color = new int[26];
55+
for (int i = 0; i < 26; i++) {
56+
if ((sub >> i & 1) == 1) continue; // 只遍历不在 sub 中的字母
57+
if (color[i] == 0 && dfs(i, color, sub)) {
58+
return true;
59+
}
60+
}
61+
return false;
62+
}
63+
64+
private boolean dfs(int x, int[] color, int sub) {
65+
color[x] = 1;
66+
for (int y : g[x]) {
67+
if ((sub >> y & 1) == 1) continue; // 只遍历不在 sub 中的字母
68+
if (color[y] == 1) return true;
69+
if (color[y] == 0 && dfs(y, color, sub)) return true;
70+
}
71+
color[x] = 2;
72+
return false;
73+
}
74+
}
75+
/*
76+
3435. 最短公共超序列的字母出现频率
77+
https://leetcode.cn/problems/frequencies-of-shortest-supersequences/description/
78+
79+
第 434 场周赛 T4。
80+
81+
给你一个字符串数组 words 。请你找到 words 所有 最短公共超序列 ,且确保它们互相之间无法通过排列得到。
82+
最短公共超序列 指的是一个字符串,words 中所有字符串都是它的子序列,且它的长度 最短 。
83+
请你返回一个二维整数数组 freqs ,表示所有的最短公共超序列,其中 freqs[i] 是一个长度为 26 的数组,它依次表示一个最短公共超序列的所有小写英文字母的出现频率。你可以以任意顺序返回这个频率数组。
84+
排列 指的是一个字符串中所有字母重新安排顺序以后得到的字符串。
85+
一个 子序列 是从一个字符串中删除一些(也可以不删除)字符后,剩余字符不改变顺序连接得到的 非空 字符串。
86+
提示:
87+
1 <= words.length <= 256
88+
words[i].length == 2
89+
words 中所有字符串由不超过 16 个互不相同的小写英文字母组成。
90+
words 中的字符串互不相同。
91+
92+
贪心构造 + 枚举子集 + 有向图判环 + 优化。
93+
1、性质:如果一个字母在答案中出现了两次,那么加在最左和最右是最优的
94+
比如 a,加在最左和最右,那么可以满足所有 a* 和 *a 的字符串
95+
小问题:答案有必要有三个相同字母吗
96+
2、每种字母至多是 2
97+
3、16 种字母,每种字母要么出现 1 次,要么出现 2 次
98+
2^16 种不同的方案
99+
4、枚举具体的方案(哪些字母出现 1 次,哪些出现 2 次)
100+
判断是否合法
101+
5、求出所有合法方案中最短的
102+
6、如何判断是否合法?
103+
s 字符串相当于一个约束:s[0] 在 s[1] 的左边
104+
这种位置关系可以抽象成【有向图】
105+
7、问题变成判断【有向图】是否有环
106+
8、有向图无环 -> 合法方案
107+
相似题目: 207. 课程表
108+
https://leetcode.cn/problems/course-schedule/
109+
rating 3025 (clist.by)
110+
*/
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
public class Solution3432Tests {
5+
private final Solution3432 solution3432 = new Solution3432();
6+
7+
@Test
8+
public void example1() {
9+
int[] nums = {10, 10, 3, 7, 6};
10+
int expected = 4;
11+
Assertions.assertEquals(expected, solution3432.countPartitions(nums));
12+
}
13+
14+
@Test
15+
public void example2() {
16+
int[] nums = {1, 2, 2};
17+
int expected = 0;
18+
Assertions.assertEquals(expected, solution3432.countPartitions(nums));
19+
}
20+
21+
@Test
22+
public void example3() {
23+
int[] nums = {2, 4, 6, 8};
24+
int expected = 3;
25+
Assertions.assertEquals(expected, solution3432.countPartitions(nums));
26+
}
27+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
import java.util.List;
5+
6+
public class Solution3433Tests {
7+
private final Solution3433 solution3433 = new Solution3433();
8+
9+
@Test
10+
public void example1() {
11+
int numberOfUsers = 2;
12+
List<List<String>> events = UtUtils.stringToStringList2("""
13+
[["MESSAGE","10","id1 id0"],["OFFLINE","11","0"],["MESSAGE","71","HERE"]]
14+
""");
15+
int[] expected = {2, 2};
16+
Assertions.assertArrayEquals(expected, solution3433.countMentions(numberOfUsers, events));
17+
}
18+
19+
@Test
20+
public void example2() {
21+
int numberOfUsers = 2;
22+
List<List<String>> events = UtUtils.stringToStringList2("""
23+
[["MESSAGE","10","id1 id0"],["OFFLINE","11","0"],["MESSAGE","12","ALL"]]
24+
""");
25+
int[] expected = {2, 2};
26+
Assertions.assertArrayEquals(expected, solution3433.countMentions(numberOfUsers, events));
27+
}
28+
29+
@Test
30+
public void example3() {
31+
int numberOfUsers = 2;
32+
List<List<String>> events = UtUtils.stringToStringList2("""
33+
[["OFFLINE","10","0"],["MESSAGE","12","HERE"]]
34+
""");
35+
int[] expected = {0, 1};
36+
Assertions.assertArrayEquals(expected, solution3433.countMentions(numberOfUsers, events));
37+
}
38+
}
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+
public class Solution3434Tests {
5+
private final Solution3434 solution3434 = new Solution3434();
6+
7+
@Test
8+
public void example1() {
9+
int[] nums = {1, 2, 3, 4, 5, 6};
10+
int k = 1;
11+
int expected = 2;
12+
Assertions.assertEquals(expected, solution3434.maxFrequency(nums, k));
13+
}
14+
15+
@Test
16+
public void example2() {
17+
int[] nums = {10, 2, 3, 4, 5, 5, 4, 3, 2, 2};
18+
int k = 10;
19+
int expected = 4;
20+
Assertions.assertEquals(expected, solution3434.maxFrequency(nums, k));
21+
}
22+
}

0 commit comments

Comments
(0)

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