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 e1cb4c3

Browse files
committed
第432场周赛T1~T4 (4)
1 parent 27d7020 commit e1cb4c3

File tree

8 files changed

+382
-0
lines changed

8 files changed

+382
-0
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import java.util.ArrayList;
2+
import java.util.List;
3+
4+
public class Solution3417 {
5+
public List<Integer> zigzagTraversal(int[][] grid) {
6+
int m = grid.length;
7+
int n = grid[0].length;
8+
9+
List<Integer> ans = new ArrayList<>();
10+
boolean add = true;
11+
for (int i = 0; i < m; i++) {
12+
for (int j = 0; j < n; j++) {
13+
if (add) {
14+
if (i % 2 == 0) ans.add(grid[i][j]);
15+
else ans.add(grid[i][n - 1 - j]);
16+
}
17+
add = !add;
18+
}
19+
}
20+
return ans;
21+
}
22+
}
23+
/*
24+
3417. 跳过交替单元格的之字形遍历
25+
https://leetcode.cn/problems/zigzag-grid-traversal-with-skip/description/
26+
27+
第 432 场周赛 T1。
28+
29+
给你一个 m x n 的二维数组 grid,数组由 正整数 组成。
30+
你的任务是以 之字形 遍历 grid,同时跳过每个 交替 的单元格。
31+
之字形遍历的定义如下:
32+
- 从左上角的单元格 (0, 0) 开始。
33+
- 在当前行中向 右 移动,直到到达该行的末尾。
34+
- 下移到下一行,然后在该行中向 左 移动,直到到达该行的开头。
35+
- 继续在行间交替向右和向左移动,直到所有行都被遍历完。
36+
注意:在遍历过程中,必须跳过每个 交替 的单元格。
37+
返回一个整数数组 result,其中包含按 顺序 记录的、且跳过交替单元格后的之字形遍历中访问到的单元格值。
38+
提示:
39+
2 <= n == grid.length <= 50
40+
2 <= m == grid[i].length <= 50
41+
1 <= grid[i][j] <= 2500
42+
43+
模拟。
44+
*/
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import java.util.Arrays;
2+
3+
public class Solution3418 {
4+
public int maximumAmount(int[][] coins) {
5+
int m = coins.length;
6+
int n = coins[0].length;
7+
8+
int[][][] f = new int[m][n][3];
9+
for (int i = 0; i < m; i++) {
10+
for (int j = 0; j < n; j++) {
11+
Arrays.fill(f[i][j], (int) -1e9);
12+
}
13+
}
14+
f[0][0][0] = coins[0][0]; // 感化0次
15+
f[0][0][1] = Math.max(0, f[0][0][0]); // 感化1次
16+
f[0][0][2] = Math.max(0, f[0][0][1]); // 感化2次
17+
for (int i = 0; i < m; i++) {
18+
for (int j = 0; j < n; j++) {
19+
for (int k0 = 0; k0 <= 2; k0++) {
20+
if (j - 1 >= 0) {
21+
f[i][j][k0] = Math.max(f[i][j][k0], f[i][j - 1][k0] + coins[i][j]);
22+
}
23+
if (i - 1 >= 0) {
24+
f[i][j][k0] = Math.max(f[i][j][k0], f[i - 1][j][k0] + coins[i][j]);
25+
}
26+
// 感化
27+
if (coins[i][j] >= 0) continue;
28+
int k1 = k0 + 1;
29+
if (k1 > 2) continue;
30+
if (j - 1 >= 0) {
31+
f[i][j][k1] = Math.max(f[i][j][k1], f[i][j - 1][k0]);
32+
}
33+
if (i - 1 >= 0) {
34+
f[i][j][k1] = Math.max(f[i][j][k1], f[i - 1][j][k0]);
35+
}
36+
}
37+
}
38+
}
39+
return Arrays.stream(f[m - 1][n - 1]).max().orElseThrow();
40+
}
41+
}
42+
/*
43+
3418. 机器人可以获得的最大金币数
44+
https://leetcode.cn/problems/maximum-amount-of-money-robot-can-earn/description/
45+
46+
第 432 场周赛 T2。
47+
48+
给你一个 m x n 的网格。一个机器人从网格的左上角 (0, 0) 出发,目标是到达网格的右下角 (m - 1, n - 1)。在任意时刻,机器人只能向右或向下移动。
49+
网格中的每个单元格包含一个值 coins[i][j]:
50+
- 如果 coins[i][j] >= 0,机器人可以获得该单元格的金币。
51+
- 如果 coins[i][j] < 0,机器人会遇到一个强盗,强盗会抢走该单元格数值的 绝对值 的金币。
52+
机器人有一项特殊能力,可以在行程中 最多感化 2个单元格的强盗,从而防止这些单元格的金币被抢走。
53+
注意:机器人的总金币数可以是负数。
54+
返回机器人在路径上可以获得的 最大金币数 。
55+
提示:
56+
m == coins.length
57+
n == coins[i].length
58+
1 <= m, n <= 500
59+
-1000 <= coins[i][j] <= 1000
60+
61+
网格图 DP。
62+
*/
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import java.util.ArrayList;
2+
import java.util.Arrays;
3+
import java.util.List;
4+
5+
public class Solution3419 {
6+
private int n;
7+
private List<int[]>[] rg;
8+
private int[] vis;
9+
10+
public int minMaxWeight(int n, int[][] edges, int threshold) {
11+
this.n = n;
12+
rg = new ArrayList[n]; // 反图
13+
Arrays.setAll(rg, e -> new ArrayList<>());
14+
int maxWt = 0;
15+
for (int[] p : edges) {
16+
int u = p[0], v = p[1], wt = p[2];
17+
rg[v].add(new int[]{u, wt});
18+
maxWt = Math.max(maxWt, wt);
19+
}
20+
21+
vis = new int[n];
22+
int left = 0;
23+
int right = maxWt + 1;
24+
while (left < right) {
25+
int mid = left + (right - left) / 2;
26+
// 边界二分 F, F,..., F, [T, T,..., T]
27+
// ----------------------^
28+
if (checkMid(mid)) {
29+
right = mid;
30+
} else {
31+
left = mid + 1;
32+
}
33+
}
34+
return (left == maxWt + 1) ? -1 : left;
35+
}
36+
37+
private boolean checkMid(int mid) {
38+
return dfs(0, mid) == n;
39+
}
40+
41+
private int dfs(int x, int upper) {
42+
vis[x] = upper; // 避免每次重新创建 vis 数组
43+
int cnt = 1;
44+
for (int[] e : rg[x]) {
45+
int y = e[0];
46+
if (e[1] <= upper && vis[y] != upper) {
47+
cnt += dfs(y, upper);
48+
}
49+
}
50+
return cnt;
51+
}
52+
}
53+
/*
54+
3419. 图的最大边权的最小值
55+
https://leetcode.cn/problems/minimize-the-maximum-edge-weight-of-graph/description/
56+
57+
第 432 场周赛 T3。
58+
59+
给你两个整数 n 和 threshold ,同时给你一个 n 个节点的 有向 带权图,节点编号为 0 到 n - 1 。这个图用 二维 整数数组 edges 表示,其中 edges[i] = [Ai, Bi, Wi] 表示节点 Ai 到节点 Bi 之间有一条边权为 Wi的有向边。
60+
你需要从这个图中删除一些边(也可能 不 删除任何边),使得这个图满足以下条件:
61+
- 所有其他节点都可以到达节点 0 。
62+
- 图中剩余边的 最大 边权值尽可能小。
63+
- 每个节点都 至多 有 threshold 条出去的边。
64+
请你返回删除必要的边后,最大 边权的 最小值 为多少。如果无法满足所有的条件,请你返回 -1 。
65+
提示:
66+
2 <= n <= 10^5
67+
1 <= threshold <= n - 1
68+
1 <= edges.length <= min(105, n * (n - 1) / 2).
69+
edges[i].length == 3
70+
0 <= Ai, Bi < n
71+
Ai != Bi
72+
1 <= Wi <= 10^6
73+
一对节点之间 可能 会有多条边,但它们的权值互不相同。
74+
75+
二分答案。
76+
threshold 是多余的。请大胆二分。
77+
rating 2249 (clist.by)
78+
*/
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import java.util.ArrayDeque;
2+
import java.util.ArrayList;
3+
import java.util.Arrays;
4+
import java.util.Deque;
5+
import java.util.List;
6+
7+
public class Solution3420 {
8+
public long countNonDecreasingSubarrays(int[] nums, int k) {
9+
int n = nums.length;
10+
List<Integer>[] g = new ArrayList[n];
11+
Arrays.setAll(g, e -> new ArrayList<>());
12+
int[] posR = new int[n];
13+
Arrays.fill(posR, n);
14+
Deque<Integer> st = new ArrayDeque<>();
15+
for (int i = 0; i < n; i++) {
16+
int x = nums[i];
17+
while (!st.isEmpty() && x >= nums[st.peek()]) {
18+
posR[st.pop()] = i;
19+
}
20+
// 循环结束后,栈顶就是左侧 > x 的最近元素了
21+
if (!st.isEmpty()) {
22+
g[st.peek()].add(i);
23+
}
24+
st.push(i);
25+
}
26+
27+
long ans = 0;
28+
int cnt = 0;
29+
int l = 0; // 窗口左端点
30+
Deque<Integer> dq = new ArrayDeque<>(); // 单调队列维护最大值
31+
for (int r = 0; r < n; r++) { // 窗口右端点
32+
int x = nums[r];
33+
// x 进入窗口
34+
while (!dq.isEmpty() && nums[dq.peekLast()] <= x) {
35+
dq.pollLast(); // 维护 q 的单调性
36+
}
37+
dq.addLast(r);
38+
39+
// 由于队首到队尾单调递减,所以窗口最大值就是队首
40+
cnt += nums[dq.peekFirst()] - x;
41+
42+
// 操作次数太多,缩小窗口
43+
while (cnt > k) {
44+
int out = nums[l]; // 离开窗口的元素
45+
for (int i : g[l]) {
46+
if (i > r) {
47+
break;
48+
}
49+
cnt -= (out - nums[i]) * (Math.min(posR[i], r + 1) - i);
50+
}
51+
l++;
52+
53+
// 队首已经离开窗口了
54+
if (!dq.isEmpty() && dq.peekFirst() < l) {
55+
dq.pollFirst();
56+
}
57+
}
58+
59+
ans += r - l + 1;
60+
}
61+
62+
return ans;
63+
}
64+
}
65+
/*
66+
3420. 统计 K 次操作以内得到非递减子数组的数目
67+
https://leetcode.cn/problems/count-non-decreasing-subarrays-after-k-operations/description/
68+
69+
第 432 场周赛 T4。
70+
71+
给你一个长度为 n 的数组 nums 和一个整数 k 。
72+
对于 nums 中的每一个子数组,你可以对它进行 至多 k 次操作。每次操作中,你可以将子数组中的任意一个元素增加 1 。
73+
注意 ,每个子数组都是独立的,也就是说你对一个子数组的修改不会保留到另一个子数组中。
74+
请你返回最多 k 次操作以内,有多少个子数组可以变成 非递减 的。
75+
如果一个数组中的每一个元素都大于等于前一个元素(如果前一个元素存在),那么我们称这个数组是 非递减 的。
76+
提示:
77+
1 <= nums.length <= 10^5
78+
1 <= nums[i] <= 10^9
79+
1 <= k <= 10^9
80+
81+
单调栈+单调队列。
82+
左端点元素离开窗口 本题的难点。
83+
时间复杂度 O(n)。
84+
rating 2868 (clist.by)
85+
*/
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
import java.util.List;
5+
6+
public class Solution3417Tests {
7+
private final Solution3417 solution3417 = new Solution3417();
8+
9+
@Test
10+
public void example1() {
11+
int[][] grid = UtUtils.stringToInts2("[[1,2],[3,4]]");
12+
List<Integer> expected = List.of(1, 4);
13+
Assertions.assertEquals(expected, solution3417.zigzagTraversal(grid));
14+
}
15+
16+
@Test
17+
public void example2() {
18+
int[][] grid = UtUtils.stringToInts2("[[2,1],[2,1],[2,1]]");
19+
List<Integer> expected = List.of(2, 1, 2);
20+
Assertions.assertEquals(expected, solution3417.zigzagTraversal(grid));
21+
}
22+
23+
@Test
24+
public void example3() {
25+
int[][] grid = UtUtils.stringToInts2("[[1,2,3],[4,5,6],[7,8,9]]");
26+
List<Integer> expected = List.of(1, 3, 5, 7, 9);
27+
Assertions.assertEquals(expected, solution3417.zigzagTraversal(grid));
28+
}
29+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
public class Solution3418Tests {
5+
private final Solution3418 solution3418 = new Solution3418();
6+
7+
@Test
8+
public void example1() {
9+
int[][] coins = UtUtils.stringToInts2("[[0,1,-1],[1,-2,3],[2,-3,4]]");
10+
int expected = 8;
11+
Assertions.assertEquals(expected, solution3418.maximumAmount(coins));
12+
}
13+
14+
@Test
15+
public void example2() {
16+
int[][] coins = UtUtils.stringToInts2("[[10,10,10],[10,10,10]]");
17+
int expected = 40;
18+
Assertions.assertEquals(expected, solution3418.maximumAmount(coins));
19+
}
20+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
public class Solution3419Tests {
5+
private final Solution3419 solution3419 = new Solution3419();
6+
7+
@Test
8+
public void example1() {
9+
int n = 5;
10+
int[][] edges = UtUtils.stringToInts2("[[1,0,1],[2,0,2],[3,0,1],[4,3,1],[2,1,1]]");
11+
int threshold = 2;
12+
int expected = 1;
13+
Assertions.assertEquals(expected, solution3419.minMaxWeight(n, edges, threshold));
14+
}
15+
16+
@Test
17+
public void example2() {
18+
int n = 5;
19+
int[][] edges = UtUtils.stringToInts2("[[0,1,1],[0,2,2],[0,3,1],[0,4,1],[1,2,1],[1,4,1]]");
20+
int threshold = 1;
21+
int expected = -1;
22+
Assertions.assertEquals(expected, solution3419.minMaxWeight(n, edges, threshold));
23+
}
24+
25+
@Test
26+
public void example3() {
27+
int n = 5;
28+
int[][] edges = UtUtils.stringToInts2("[[1,2,1],[1,3,3],[1,4,5],[2,3,2],[3,4,2],[4,0,1]]");
29+
int threshold = 1;
30+
int expected = 2;
31+
Assertions.assertEquals(expected, solution3419.minMaxWeight(n, edges, threshold));
32+
}
33+
34+
@Test
35+
public void example4() {
36+
int n = 5;
37+
int[][] edges = UtUtils.stringToInts2("[[1,2,1],[1,3,3],[1,4,5],[2,3,2],[4,0,1]]");
38+
int threshold = 1;
39+
int expected = -1;
40+
Assertions.assertEquals(expected, solution3419.minMaxWeight(n, edges, threshold));
41+
}
42+
}
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 Solution3420Tests {
5+
private final Solution3420 solution3420 = new Solution3420();
6+
7+
@Test
8+
public void example1() {
9+
int[] nums = {6, 3, 1, 2, 4, 4};
10+
int k = 7;
11+
long expected = 17;
12+
Assertions.assertEquals(expected, solution3420.countNonDecreasingSubarrays(nums, k));
13+
}
14+
15+
@Test
16+
public void example2() {
17+
int[] nums = {6, 3, 1, 3, 6};
18+
int k = 4;
19+
long expected = 12;
20+
Assertions.assertEquals(expected, solution3420.countNonDecreasingSubarrays(nums, k));
21+
}
22+
}

0 commit comments

Comments
(0)

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