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 0d8ee85

Browse files
committed
第149场双周赛T1~T4 & 第435场周赛T1~T4 (8)
1 parent 3ea9d82 commit 0d8ee85

16 files changed

+661
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
public class Solution3438 {
2+
public String findValidPair(String S) {
3+
char[] s = S.toCharArray();
4+
int[] cnt = new int[10];
5+
for (char c : s) {
6+
cnt[c - '0']++;
7+
}
8+
for (int i = 1; i < s.length; i++) {
9+
if (s[i - 1] == s[i]) continue;
10+
if (cnt[s[i - 1] - '0'] == s[i - 1] - '0' &&
11+
cnt[s[i] - '0'] == s[i] - '0') {
12+
return S.substring(i - 1, i + 1);
13+
}
14+
}
15+
return "";
16+
}
17+
}
18+
/*
19+
3438. 找到字符串中合法的相邻数字
20+
https://leetcode.cn/problems/find-valid-pair-of-adjacent-digits-in-string/description/
21+
22+
第 149 场双周赛 T1。
23+
24+
给你一个只包含数字的字符串 s 。如果 s 中两个 相邻 的数字满足以下条件,我们称它们是 合法的 :
25+
- 前面的数字 不等于 第二个数字。
26+
- 两个数字在 s 中出现的次数 恰好 分别等于这个数字本身。
27+
请你从左到右遍历字符串 s ,并返回最先找到的 合法 相邻数字。如果这样的相邻数字不存在,请你返回一个空字符串。
28+
提示:
29+
2 <= s.length <= 100
30+
s 只包含 '1' 到 '9' 的数字。
31+
32+
中国时间:2025年02月01日 22:30
33+
2025春节初四
34+
模拟。
35+
*/
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
public class Solution3439 {
2+
private int eventTime;
3+
private int[] startTime, endTime;
4+
5+
public int maxFreeTime(int eventTime, int k, int[] startTime, int[] endTime) {
6+
this.eventTime = eventTime;
7+
this.startTime = startTime;
8+
this.endTime = endTime;
9+
10+
int n = startTime.length;
11+
int s = 0;
12+
for (int i = 0; i < k; i++) {
13+
s += get(i);
14+
}
15+
int ans = s;
16+
for (int i = k; i <= n; i++) {
17+
s += get(i);
18+
ans = Math.max(ans, s);
19+
s -= get(i - k);
20+
}
21+
return ans;
22+
}
23+
24+
private int get(int i) {
25+
if (i == 0) {
26+
return startTime[0];
27+
}
28+
int n = startTime.length;
29+
if (i == n) {
30+
return eventTime - endTime[n - 1];
31+
}
32+
return startTime[i] - endTime[i - 1];
33+
}
34+
}
35+
/*
36+
3439. 重新安排会议得到最多空余时间 I
37+
https://leetcode.cn/problems/reschedule-meetings-for-maximum-free-time-i/description/
38+
39+
第 149 场双周赛 T2。
40+
41+
给你一个整数 eventTime 表示一个活动的总时长,这个活动开始于 t = 0 ,结束于 t = eventTime 。
42+
同时给你两个长度为 n 的整数数组 startTime 和 endTime 。它们表示这次活动中 n 个时间 没有重叠 的会议,其中第 i 个会议的时间为 [startTime[i], endTime[i]] 。
43+
你可以重新安排 至多 k 个会议,安排的规则是将会议时间平移,且保持原来的 会议时长 ,你的目的是移动会议后 最大化 相邻两个会议之间的 最长 连续空余时间。
44+
移动前后所有会议之间的 相对 顺序需要保持不变,而且会议时间也需要保持互不重叠。
45+
请你返回重新安排会议以后,可以得到的 最大 空余时间。
46+
注意,会议 不能 安排到整个活动的时间以外。
47+
提示:
48+
1 <= eventTime <= 10^9
49+
n == startTime.length == endTime.length
50+
2 <= n <= 10^5
51+
1 <= k <= n
52+
0 <= startTime[i] < endTime[i] <= eventTime
53+
endTime[i] <= startTime[i + 1] 其中 i 在范围 [0, n - 2] 之间。
54+
55+
定长滑动窗口。
56+
问题等价于:给你 n+1 个空余时间段,合并其中 k+1 个连续的空余时间段,得到的最大长度是多少?
57+
时间复杂度 O(n)。
58+
相似题目: 3440. 重新安排会议得到最多空余时间 II
59+
https://leetcode.cn/problems/reschedule-meetings-for-maximum-free-time-ii/description/
60+
*/
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
public class Solution3440 {
2+
private int eventTime;
3+
private int[] startTime, endTime;
4+
5+
public int maxFreeTime(int eventTime, int[] startTime, int[] endTime) {
6+
this.eventTime = eventTime;
7+
this.startTime = startTime;
8+
this.endTime = endTime;
9+
10+
int n = startTime.length;
11+
// 最大的三个空位所在的位置(下标)分别是 a,b,c。
12+
int a = 0, b = -1, c = -1;
13+
for (int i = 1; i <= n; i++) {
14+
int sz = get(i);
15+
if (sz > get(a)) {
16+
c = b;
17+
b = a;
18+
a = i;
19+
} else if (b < 0 || sz > get(b)) {
20+
c = b;
21+
b = i;
22+
} else if (c < 0 || sz > get(c)) {
23+
c = i;
24+
}
25+
}
26+
27+
int ans = 0;
28+
for (int i = 0; i < n; i++) {
29+
int sz = endTime[i] - startTime[i];
30+
if (i != a && i + 1 != a && sz <= get(a) ||
31+
i != b && i + 1 != b && sz <= get(b) ||
32+
sz <= get(c)) {
33+
ans = Math.max(ans, get(i) + sz + get(i + 1));
34+
} else {
35+
ans = Math.max(ans, get(i) + get(i + 1));
36+
}
37+
}
38+
return ans;
39+
}
40+
41+
private int get(int i) {
42+
if (i == 0) {
43+
return startTime[0];
44+
}
45+
int n = startTime.length;
46+
if (i == n) {
47+
return eventTime - endTime[n - 1];
48+
}
49+
return startTime[i] - endTime[i - 1];
50+
}
51+
}
52+
/*
53+
3440. 重新安排会议得到最多空余时间 II
54+
https://leetcode.cn/problems/reschedule-meetings-for-maximum-free-time-ii/description/
55+
56+
第 149 场双周赛 T3。
57+
58+
给你一个整数 eventTime 表示一个活动的总时长,这个活动开始于 t = 0 ,结束于 t = eventTime 。
59+
同时给你两个长度为 n 的整数数组 startTime 和 endTime 。它们表示这次活动中 n 个时间 没有重叠 的会议,其中第 i 个会议的时间为 [startTime[i], endTime[i]] 。
60+
你可以重新安排 至多 一个会议,安排的规则是将会议时间平移,且保持原来的 会议时长 ,你的目的是移动会议后 最大化 相邻两个会议之间的 最长 连续空余时间。
61+
请你返回重新安排会议以后,可以得到的 最大 空余时间。
62+
注意,会议 不能 安排到整个活动的时间以外,且会议之间需要保持互不重叠。
63+
注意:重新安排会议以后,会议之间的顺序可以发生改变。
64+
提示:
65+
1 <= eventTime <= 10^9
66+
n == startTime.length == endTime.length
67+
2 <= n <= 10^5
68+
0 <= startTime[i] < endTime[i] <= eventTime
69+
endTime[i] <= startTime[i + 1] 其中 i 在范围 [0, n - 2] 之间。
70+
71+
维护前三大的空位+枚举+分类讨论。
72+
时间复杂度 O(n)。
73+
相似题目: 3439. 重新安排会议得到最多空余时间 I
74+
https://leetcode.cn/problems/reschedule-meetings-for-maximum-free-time-i/description/
75+
*/
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
public class Solution3441 {
2+
public String minCostGoodCaption(String caption) {
3+
int n = caption.length();
4+
if (n < 3) {
5+
return "";
6+
}
7+
8+
char[] s = caption.toCharArray();
9+
int[][] f = new int[n + 1][26];
10+
int[] minJ = new int[n + 1];
11+
int[][] nxt = new int[n + 1][26];
12+
for (int i = n - 1; i >= 0; i--) {
13+
int mn = Integer.MAX_VALUE;
14+
for (int j = 0; j < 26; j++) {
15+
int res = f[i + 1][j] + Math.abs(s[i] - 'a' - j);
16+
int res2 = i <= n - 6 ? f[i + 3][minJ[i + 3]] + Math.abs(s[i] - 'a' - j) + Math.abs(s[i + 1] - 'a' - j) + Math.abs(s[i + 2] - 'a' - j) : Integer.MAX_VALUE;
17+
if (res2 < res || res2 == res && minJ[i + 3] < j) {
18+
res = res2;
19+
nxt[i][j] = minJ[i + 3]; // 记录转移来源
20+
} else {
21+
nxt[i][j] = j; // 记录转移来源
22+
}
23+
f[i][j] = res;
24+
if (res < mn) {
25+
mn = res;
26+
minJ[i] = j; // 记录最小的 f[i][j] 中的 j 是多少
27+
}
28+
}
29+
}
30+
31+
char[] ans = new char[n];
32+
int i = 0;
33+
int j = minJ[0];
34+
while (i < n) {
35+
ans[i] = (char) ('a' + j);
36+
int k = nxt[i][j];
37+
if (k == j) {
38+
i++;
39+
} else {
40+
ans[i + 2] = ans[i + 1] = ans[i];
41+
i += 3;
42+
j = k;
43+
}
44+
}
45+
return new String(ans);
46+
}
47+
48+
}
49+
/*
50+
3441. 变成好标题的最少代价
51+
https://leetcode.cn/problems/minimum-cost-good-caption/description/
52+
53+
第 149 场双周赛 T4。
54+
55+
给你一个长度为 n 的字符串 caption 。如果字符串中 每一个 字符都位于连续出现 至少 3 次 的组中,那么我们称这个字符串是 好 标题。
56+
比方说:
57+
- "aaabbb" 和 "aaaaccc" 都是 好 标题。
58+
- "aabbb" 和 "ccccd" 都 不是 好标题。
59+
你可以对字符串执行以下操作 任意 次:
60+
选择一个下标 i(其中 0 <= i < n )然后将该下标处的字符变为:
61+
- 该字符在字母表中 前 一个字母(前提是 caption[i] != 'a' )
62+
- 该字符在字母表中 后 一个字母(caption[i] != 'z' )
63+
你的任务是用 最少 操作次数将 caption 变为 好 标题。如果存在 多种 好标题,请返回它们中 字典序最小 的一个。如果 无法 得到好标题,请你返回一个空字符串 "" 。
64+
在字符串 a 和 b 中,如果两个字符串第一个不同的字符处,字符串 a 的字母比 b 的字母在字母表里出现的顺序更早,那么我们称字符串 a 的 字典序 比 b 小 。如果两个字符串前 min(a.length, b.length) 个字符都相同,那么较短的一个字符串字典序比另一个字符串小。
65+
提示:
66+
1 <= caption.length <= 5 * 10^4
67+
caption 只包含小写英文字母。
68+
69+
枚举字母+DP。
70+
https://leetcode.cn/problems/minimum-cost-good-caption/solutions/3061609/zhuang-tai-ji-dp-shu-chu-ju-ti-fang-an-p-kjry/
71+
rating 2780 (clist.by)
72+
*/
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
public class Solution3442 {
2+
public int maxDifference(String s) {
3+
int[] cnt = new int[26];
4+
for (char c : s.toCharArray()) {
5+
cnt[c - 'a']++;
6+
}
7+
8+
int maxOdd = 0, minEven = Integer.MAX_VALUE;
9+
for (int c : cnt) {
10+
if (c % 2 == 1) maxOdd = Math.max(maxOdd, c);
11+
else if (c > 0) minEven = Math.min(minEven, c);
12+
}
13+
return maxOdd - minEven;
14+
}
15+
}
16+
/*
17+
3442. 奇偶频次间的最大差值 I
18+
https://leetcode.cn/problems/maximum-difference-between-even-and-odd-frequency-i/description/
19+
20+
第 435 场周赛 T1。
21+
22+
给你一个由小写英文字母组成的字符串 s 。请你找出字符串中两个字符的出现频次之间的 最大 差值,这两个字符需要满足:
23+
- 一个字符在字符串中出现 偶数次 。
24+
- 另一个字符在字符串中出现 奇数次 。
25+
返回 最大 差值,计算方法是出现 奇数次 字符的次数 减去 出现 偶数次 字符的次数。
26+
提示:
27+
3 <= s.length <= 100
28+
s 仅由小写英文字母组成。
29+
s 至少由一个出现奇数次的字符和一个出现偶数次的字符组成。
30+
31+
中国时间:2025年02月02日 10:30
32+
2025春节初五
33+
统计频次。
34+
*/
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
public class Solution3443 {
2+
public int maxDistance(String s, int k) {
3+
int x = 0, y = 0;
4+
int ans = 0;
5+
for (int i = 0; i < s.length(); i++) {
6+
char c = s.charAt(i);
7+
if (c == 'N') y++;
8+
else if (c == 'S') y--;
9+
else if (c == 'E') x++;
10+
else x--;
11+
ans = Math.max(ans, Math.min(Math.abs(x) + Math.abs(y) + k * 2, i + 1));
12+
}
13+
return ans;
14+
}
15+
}
16+
/*
17+
3443. K 次修改后的最大曼哈顿距离
18+
https://leetcode.cn/problems/maximum-manhattan-distance-after-k-changes/description/
19+
20+
第 435 场周赛 T2。
21+
22+
给你一个由字符 'N'、'S'、'E' 和 'W' 组成的字符串 s,其中 s[i] 表示在无限网格中的移动操作:
23+
- 'N':向北移动 1 个单位。
24+
- 'S':向南移动 1 个单位。
25+
- 'E':向东移动 1 个单位。
26+
- 'W':向西移动 1 个单位。
27+
初始时,你位于原点 (0, 0)。你 最多 可以修改 k 个字符为任意四个方向之一。
28+
请找出在 按顺序 执行所有移动操作过程中的 任意时刻 ,所能达到的离原点的 最大曼哈顿距离 。
29+
曼哈顿距离 定义为两个坐标点 (xi, yi) 和 (xj, yj) 的横向距离绝对值与纵向距离绝对值之和,即 |xi - xj| + |yi - yj|。
30+
提示:
31+
1 <= s.length <= 10^5
32+
0 <= k <= s.length
33+
s 仅由 'N'、'S'、'E' 和 'W' 。
34+
35+
每操作一次,曼哈顿距离都会增大 2,但这不会超过移动的次数 i+1。
36+
所以执行完 s[i] 后的答案为 min(|x|+|y|+2k,i+1)
37+
时间复杂度 O(n)。
38+
*/
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import java.util.Arrays;
2+
3+
public class Solution3444 {
4+
private static final long INF = (long) 1e18;
5+
private long[] lcms;
6+
private long[][] memo;
7+
8+
public int minimumIncrements(int[] nums, int[] target) {
9+
int n = nums.length;
10+
int m = target.length;
11+
12+
// 预处理 target 的所有子集的 LCM
13+
lcms = new long[1 << m];
14+
lcms[0] = 1;
15+
for (int i = 0; i < m; i++) {
16+
int bit = 1 << i;
17+
for (int mask = 0; mask < bit; mask++) {
18+
lcms[bit | mask] = getLCM(target[i], lcms[mask]);
19+
}
20+
}
21+
22+
memo = new long[n][1 << m];
23+
for (int i = 0; i < n; i++) {
24+
Arrays.fill(memo[i], -1);
25+
}
26+
return (int) dfs(n - 1, (1 << m) - 1, nums);
27+
}
28+
29+
private long dfs(int i, int j, int[] nums) {
30+
if (j == 0) return 0;
31+
if (i < 0) { // 不能有剩余元素
32+
return INF;
33+
}
34+
if (memo[i][j] != -1) return memo[i][j];
35+
long res = dfs(i - 1, j, nums); // 不修改 nums[i]
36+
for (int sub = j; sub > 0; sub = (sub - 1) & j) { // 枚举 j 的所有非空子集
37+
long l = lcms[sub];
38+
res = Math.min(res, dfs(i - 1, j ^ sub, nums) + (l - nums[i] % l) % l);
39+
}
40+
return memo[i][j] = res;
41+
}
42+
43+
private long getGCD(long num1, long num2) {
44+
return num1 == 0 ? num2 : getGCD(num2 % num1, num1);
45+
}
46+
47+
private long getLCM(long num1, long num2) {
48+
return num1 / getGCD(num1, num2) * num2;
49+
}
50+
}
51+
/*
52+
3444. 使数组包含目标值倍数的最少增量
53+
https://leetcode.cn/problems/minimum-increments-for-target-multiples-in-an-array/description/
54+
55+
第 435 场周赛 T3。
56+
57+
给你两个数组 nums 和 target 。
58+
在一次操作中,你可以将 nums 中的任意一个元素递增 1 。
59+
返回要使 target 中的每个元素在 nums 中 至少 存在一个倍数所需的 最少操作次数 。
60+
提示:
61+
1 <= nums.length <= 5 * 10^4
62+
1 <= target.length <= 4
63+
target.length <= nums.length
64+
1 <= nums[i], target[i] <= 10^4
65+
66+
子集状压 DP:记忆化搜索。
67+
rating 2346 (clist.by)
68+
*/

0 commit comments

Comments
(0)

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