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 18be595

Browse files
committed
第164场双周赛T1~T4 & 第465场周赛T1~T4 (8)
1 parent 240159d commit 18be595

16 files changed

+732
-0
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import java.util.HashMap;
2+
import java.util.Map;
3+
4+
public class Solution3663 {
5+
public int getLeastFrequentDigit(int n) {
6+
Map<Integer, Integer> cnt = new HashMap<>();
7+
while (n > 0) {
8+
int d = n % 10;
9+
cnt.merge(d, 1, Integer::sum);
10+
n /= 10;
11+
}
12+
13+
int mn = Integer.MAX_VALUE;
14+
int ans = 0;
15+
for (int x = 0; x <= 9; x++) {
16+
if (!cnt.containsKey(x)) continue;
17+
Integer c = cnt.get(x);
18+
if (c < mn) {
19+
ans = x;
20+
mn = c;
21+
}
22+
}
23+
return ans;
24+
}
25+
}
26+
/*
27+
3663. 出现频率最低的数字
28+
https://leetcode.cn/problems/find-the-least-frequent-digit/description/
29+
30+
第 164 场双周赛 T1。
31+
32+
给你一个整数 n,找出在其十进制表示中出现频率 最低 的数字。如果多个数字的出现频率相同,则选择 最小 的那个数字。
33+
以整数形式返回所选的数字。
34+
数字 x 的出现频率是指它在 n 的十进制表示中的出现次数。
35+
提示:
36+
1 <= n <= 2^31 - 1
37+
38+
模拟。
39+
时间复杂度 O(logn)。
40+
*/
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
public class Solution3664 {
2+
public int score(String[] cards, char x) {
3+
// 统计频次
4+
int[] x_ = new int[10]; // 'a' 到 'j' 之间
5+
int[] _x = new int[10];
6+
int xx = 0;
7+
for (String s : cards) {
8+
char c0 = s.charAt(0), c1 = s.charAt(1);
9+
if (c0 == x && c1 == x) {
10+
xx++;
11+
} else if (c0 == x) {
12+
x_[c1 - 'a']++;
13+
} else if (c1 == x) {
14+
_x[c0 - 'a']++;
15+
}
16+
}
17+
18+
int[] res1 = getSumAndMax(x_);
19+
int[] res2 = getSumAndMax(_x);
20+
int sum1 = res1[0], max1 = res1[1];
21+
int sum2 = res2[0], max2 = res2[1];
22+
23+
int ans = 0;
24+
// 枚举分配 k 个 xx 给第一组,其余的 xx 给第二组
25+
for (int k = 0; k <= xx; k++) {
26+
int score1 = calcScore(sum1, max1, k);
27+
int score2 = calcScore(sum2, max2, xx - k);
28+
ans = Math.max(ans, score1 + score2);
29+
}
30+
return ans;
31+
}
32+
33+
// 计算出现次数之和 sum,出现次数最大值 mxC
34+
private int[] getSumAndMax(int[] cnt) {
35+
int sum = 0, mxC = 0;
36+
for (int c : cnt) {
37+
sum += c;
38+
mxC = Math.max(mxC, c);
39+
}
40+
return new int[]{sum, mxC};
41+
}
42+
43+
// 计算这一组在得到 k 个 xx 后的得分
44+
private int calcScore(int sum, int mx, int k) {
45+
sum += k;
46+
mx = Math.max(mx, k);
47+
return Math.min(sum / 2, sum - mx);
48+
}
49+
}
50+
/*
51+
3664. 两个字母卡牌游戏
52+
https://leetcode.cn/problems/two-letter-card-game/description/
53+
54+
第 164 场双周赛 T2。
55+
56+
给你一副由字符串数组 cards 表示的牌,每张牌上都显示两个小写字母。
57+
同时给你一个字母 x。你按照以下规则进行游戏:
58+
- 从 0 分开始。
59+
- 在每一轮中,你必须从牌堆中找到两张 兼容的 牌,这两张牌对应的字符串都包含字母 x。
60+
- 移除这对牌并获得 1 分。
61+
- 当你再也找不到兼容的牌对时,游戏结束。
62+
返回在最优策略下你能获得的 最大 分数。
63+
如果两张牌的字符串在 恰好 1 个位置上不同,则它们是兼容的。
64+
提示:
65+
2 <= cards.length <= 10^5
66+
cards[i].length == 2
67+
每个 cards[i] 仅由 'a' 到 'j' 之间的小写英文字母组成。
68+
x 是一个 'a' 到 'j' 之间的小写英文字母。
69+
70+
枚举。
71+
时间复杂度 O(n + C)。其中 C = 10。
72+
*/
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import java.util.Arrays;
2+
3+
public class Solution3665 {
4+
private static final int MOD = (int) (1e9 + 7);
5+
private int[][] grid;
6+
private long[][][] memo;
7+
8+
public int uniquePaths(int[][] grid) {
9+
this.grid = grid;
10+
int m = grid.length, n = grid[0].length;
11+
memo = new long[m][n][2];
12+
for (int i = 0; i < m; i++) {
13+
for (int j = 0; j < n; j++) {
14+
Arrays.fill(memo[i][j], -1);
15+
}
16+
}
17+
return (int) dfs(m - 1, n - 1, 0);
18+
}
19+
20+
private long dfs(int i, int j, int k) {
21+
if (i < 0 || j < 0) return 0; // 出界
22+
if (i == 0 && j == 0) return 1; // 到达起点
23+
if (memo[i][j][k] != -1) return memo[i][j][k];
24+
long res;
25+
if (grid[i][j] == 0) { // 没有镜子,随便走
26+
res = (dfs(i, j - 1, 0) + dfs(i - 1, j, 1)) % MOD;
27+
} else if (k == 0) { // 从下边过来,反射到左边
28+
res = dfs(i - 1, j, 1);
29+
} else { // 从右边过来,反射到上边
30+
res = dfs(i, j - 1, 0);
31+
}
32+
return memo[i][j][k] = res;
33+
}
34+
}
35+
/*
36+
3665. 统计镜子反射路径数目
37+
https://leetcode.cn/problems/twisted-mirror-path-count/description/
38+
39+
第 164 场双周赛 T3。
40+
41+
给你一个 m x n 的二进制网格 grid,其中:
42+
- grid[i][j] == 0 表示一个空格子。
43+
- grid[i][j] == 1 表示一面镜子。
44+
一个机器人从网格的左上角 (0, 0) 出发,想要到达右下角 (m - 1, n - 1)。它只能向 右 或向 下 移动。如果机器人试图移入一个有镜子的格子,它会在进入该格子前被 反射:
45+
- 如果它试图向 右 移动进入镜子,它会被转向 下 方,并移动到镜子正下方的格子里。
46+
- 如果它试图向 下 移动进入镜子,它会被转向 右 方,并移动到镜子正右方的格子里。
47+
如果这次反射会导致机器人移动到网格边界之外,则该路径被视为无效,不应被计数。
48+
返回从 (0, 0) 到 (m - 1, n - 1) 不同的有效路径数量。
49+
由于答案可能非常大,请将其返回对 10^9 + 7 取模 的结果。
50+
注意:如果一次反射将机器人移动到一个有镜子的格子,机器人会立即再次被反射。这次反射的方向取决于它进入该镜子的方向:如果它是向右移动进入的,它将被转向下方;如果它是向下移动进入的,它将被转向右方。
51+
提示:
52+
m == grid.length
53+
n == grid[i].length
54+
2 <= m, n <= 500
55+
grid[i][j] 的值为 0 或 1。
56+
grid[0][0] == grid[m - 1][n - 1] == 0
57+
58+
记忆化搜索。
59+
时间复杂度 O(mn)。
60+
*/
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
public class Solution3666 {
2+
public int minOperations(String s, int k) {
3+
int n = s.length();
4+
int c = 0;
5+
for (int i = 0; i < n; i++) {
6+
if (s.charAt(i) == '0') {
7+
c++;
8+
}
9+
}
10+
if (c == 0) {
11+
return 0;
12+
}
13+
if (k % 2 == 0 && c % 2 != 0) {
14+
return -1;
15+
}
16+
if (k == n) {
17+
return c == n ? 1 : -1;
18+
}
19+
20+
int m0 = (c + k - 1) / k;
21+
int step = 1;
22+
if (k % 2 == 1) {
23+
if (m0 % 2 != c % 2) {
24+
m0++;
25+
}
26+
step = 2;
27+
}
28+
29+
long m = m0;
30+
while (true) {
31+
if (m % 2 == 1) {
32+
if (m * k <= (long) n * (m - 1) + c) {
33+
return (int) m;
34+
}
35+
} else {
36+
if (m * k <= (long) n * m - c) {
37+
return (int) m;
38+
}
39+
}
40+
m += step;
41+
}
42+
}
43+
}
44+
/*
45+
3666. 使二进制字符串全为 1 的最少操作次数
46+
https://leetcode.cn/problems/minimum-operations-to-equalize-binary-string/description/
47+
48+
第 164 场双周赛 T4。
49+
50+
给你一个二进制字符串 s 和一个整数 k。
51+
在一次操作中,你必须选择 恰好 k 个 不同的 下标,并将每个 '0' 翻转 为 '1',每个 '1' 翻转为 '0'。
52+
返回使字符串中所有字符都等于 '1' 所需的 最少 操作次数。如果不可能,则返回 -1。
53+
提示:
54+
1 <= s.length <= 10^5
55+
s[i] 的值为 '0' 或 '1'。
56+
1 <= k <= s.length
57+
58+
数学。
59+
https://chat.deepseek.com/a/chat/s/1a003690-eb28-4cfd-9fa2-594bf43a252e
60+
1. 统计零的个数:首先统计字符串中 '0' 的个数(记为 c)。如果 c 为零,说明字符串已经是全 '1',直接返回 0。
61+
2. 检查可行性:
62+
- 如果 k 是偶数且 c 是奇数,直接返回 -1,因为无法通过任何操作次数使所有字符变为 '1'。
63+
- 如果 k 等于字符串长度 n,只有在 c 等于 n 时返回 1,否则返回 -1。
64+
3. 计算最小操作次数:
65+
- 计算初始的最小操作次数 m0,即 ceil(c / k)。
66+
- 如果 k 是奇数,确保 m0 与 c 的奇偶性相同;否则,保持 m0 不变。
67+
- 从 m0 开始,按照步长(k 为奇数时步长为 2,否则为 1)递增,检查条件是否满足:
68+
- 如果 m 是奇数,检查 m * k <= n * (m - 1) + c。
69+
- 如果 m 是偶数,检查 m * k <= n * m - c。
70+
- 一旦条件满足,返回当前的 m。
71+
时间复杂度 O(n)。
72+
*/
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import java.util.ArrayList;
2+
import java.util.HashSet;
3+
import java.util.List;
4+
import java.util.Set;
5+
6+
public class Solution3668 {
7+
public int[] recoverOrder(int[] order, int[] friends) {
8+
Set<Integer> friendsSet = new HashSet<>();
9+
for (int v : friends) {
10+
friendsSet.add(v);
11+
}
12+
List<Integer> ans = new ArrayList<>();
13+
for (int v : order) {
14+
if (friendsSet.contains(v)) ans.add(v);
15+
}
16+
return ans.stream().mapToInt(Integer::intValue).toArray();
17+
}
18+
}
19+
/*
20+
3668. 重排完成顺序
21+
https://leetcode.cn/problems/restore-finishing-order/description/
22+
23+
第 465 场周赛 T1。
24+
25+
给你一个长度为 n 的整数数组 order 和一个整数数组 friends。
26+
- order 包含从 1 到 n 的每个整数,且 恰好出现一次 ,表示比赛中参赛者按照 完成顺序 的 ID。
27+
- friends 包含你朋友们的 ID,按照 严格递增 的顺序排列。friends 中的每个 ID 都保证出现在 order 数组中。
28+
请返回一个数组,包含你朋友们的 ID,按照他们的 完成顺序 排列。
29+
提示:
30+
1 <= n == order.length <= 100
31+
order 包含从 1 到 n 的每个整数,且恰好出现一次
32+
1 <= friends.length <= min(8, n)
33+
1 <= friends[i] <= n
34+
friends 是严格递增的
35+
36+
哈希表。
37+
时间复杂度 O(n)。
38+
*/
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import java.util.ArrayList;
2+
import java.util.Arrays;
3+
import java.util.List;
4+
5+
public class Solution3669 {
6+
private static final int MX = (int) (1e5 + 5);
7+
private static final List<Integer>[] divisors = new ArrayList[MX];
8+
9+
static {
10+
// 预处理每个数的因子
11+
Arrays.setAll(divisors, e -> new ArrayList<>());
12+
for (int i = 1; i < MX; i++) {
13+
for (int j = i; j < MX; j += i) { // 枚举 i 的倍数 j
14+
divisors[j].add(i); // i 是 j 的因子
15+
}
16+
}
17+
}
18+
19+
public int[] minDifference(int n, int k) {
20+
int[] path = new int[k];
21+
dfs(k - 1, n, Integer.MAX_VALUE, 0, path);
22+
return ans;
23+
}
24+
25+
private int minDiff = Integer.MAX_VALUE;
26+
private int[] ans;
27+
28+
private void dfs(int i, int n, int mn, int mx, int[] path) {
29+
if (i == 0) {
30+
int d = Math.max(mx, n) - Math.min(mn, n); // 最后一个数是 n
31+
if (d < minDiff) {
32+
minDiff = d;
33+
path[i] = n;
34+
ans = path.clone();
35+
}
36+
return;
37+
}
38+
for (int d : divisors[n]) { // 枚举 x 的因子
39+
path[i] = d; // 直接覆盖,无需恢复现场
40+
dfs(i - 1, n / d, Math.min(mn, d), Math.max(mx, d), path);
41+
}
42+
}
43+
}
44+
/*
45+
3669. K 因数分解
46+
https://leetcode.cn/problems/balanced-k-factor-decomposition/description/
47+
48+
第 465 场周赛 T2。
49+
50+
给你两个整数 n 和 k,将数字 n 恰好分割成 k 个正整数,使得这些整数的 乘积 等于 n。
51+
返回一个分割方案,使得这些数字中 最大值 和 最小值 之间的 差值 最小化。结果可以以 任意顺序 返回。
52+
提示:
53+
4 <= n <= 10^5
54+
2 <= k <= 5
55+
k 严格小于 n 的正因数的总数。
56+
57+
暴搜。
58+
时间复杂度 O(D^k)。其中 D <= 128。测试表明,当 n=90720,k=5 时节点个数达到最大,为 254816。
59+
*/

0 commit comments

Comments
(0)

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