Skip to content

Commit cfcdc82

Browse files
committed
weekly contest 341
1 parent 6970146 commit cfcdc82

File tree

4 files changed

+509
-0
lines changed

4 files changed

+509
-0
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ leetcode url: <https://leetcode.cn/u/cctest/>
66

77

88

9+
* ☀️ [weekly contest 341](src/main/java/weekly/wk341.java) 模拟 | 美剧 | 贪心 | 树形dp
10+
* ☀️ [weekly contest 340](src/main/java/weekly/wk340.java) 模拟 | 哈希 | 贪心 | bfs+优化
911
* ☀️ [weekly contest 339](src/main/java/weekly/wk339.java) 模拟 | 哈希 | 贪心 | 平衡树
1012
* ☀️ [weekly contest 338](src/main/java/weekly/wk338.java) 贪心 | 谈心 | 前缀和+二分 | 拓扑排序
1113
* ☀️ [weekly contest 337](src/main/java/weekly/wk337.java) 模拟 | 模拟 | 回溯 | 同余分组
@@ -54,6 +56,8 @@ leetcode url: <https://leetcode.cn/u/cctest/>
5456
* 🐶 [weekly contest 290](src/main/java/weekly/wk290.java)
5557
* 🐭 [weekly contest 280](src/main/java/weekly/wk289.java)
5658

59+
60+
* 🐸 [biweekly contest 102](src/main/java/weekly/wkb102.java) 模拟 | 前缀和 | bfs+dfs | Dijkstra
5761
* 🐸 [biweekly contest 101](src/main/java/weekly/wkb101.java) 哈希 | 滑动窗口 | 并查集 | BFS
5862
* 🐸 [biweekly contest 100](src/main/java/weekly/wkb100.java) 四维 | 贪心 | 堆 | 二分
5963
* 🐸 [biweekly contest 99](src/main/java/weekly/wkb99.java) 贪心 | 递推 | 区间合并 | 换根DP

src/main/java/weekly/wk340.java

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
package weekly;
2+
3+
import java.util.ArrayDeque;
4+
import java.util.ArrayList;
5+
import java.util.Arrays;
6+
import java.util.Deque;
7+
import java.util.HashMap;
8+
import java.util.HashSet;
9+
import java.util.LinkedList;
10+
import java.util.List;
11+
import java.util.Map;
12+
import java.util.Queue;
13+
import java.util.Set;
14+
15+
public class wk340 {
16+
17+
public static boolean isPrime(int n) {
18+
if (n == 0 || n == 1) {
19+
return false;
20+
}
21+
for (int i = 2; i <= (int) Math.sqrt(n); i++) {
22+
if (n % i == 0) {
23+
return false;
24+
}
25+
}
26+
return true;
27+
}
28+
29+
//求质数
30+
public int diagonalPrime(int[][] nums) {
31+
int ans = 0;
32+
for (int i = 0; i < nums.length; i++) {
33+
if (isPrime(nums[i][i])) {
34+
ans = Math.max(nums[i][i], ans);
35+
}
36+
if (isPrime(nums[i][nums.length - i - 1])) {
37+
ans = Math.max(nums[i][nums.length - i - 1], ans);
38+
}
39+
}
40+
return ans;
41+
}
42+
43+
44+
// 哈希分组+计算增量或前缀和
45+
public long[] distance(int[] nums) {
46+
long[] arr = new long[nums.length];
47+
Map<Integer, List<Integer>> map = new HashMap<>();
48+
49+
for (int i = 0; i < nums.length; i++) {
50+
if (!map.containsKey(nums[i])) map.put(nums[i], new ArrayList<>());
51+
map.get(nums[i]).add(i);
52+
}
53+
for (List<Integer> list : map.values()) {
54+
long sum = 0;
55+
for (int i = 1; i < list.size(); i++) {
56+
sum += list.get(i) - list.get(0);
57+
}
58+
59+
//最左侧直接求差值和
60+
arr[list.get(0)] = sum;
61+
62+
for (int i = 1; i < list.size(); i++) {
63+
long dis = list.get(i) - list.get(i - 1);
64+
//增加了i个dis,减少了(list.size-i)个ids
65+
sum += (i - (list.size() - i)) * dis;
66+
arr[list.get(i)] = sum;
67+
}
68+
69+
}
70+
return arr;
71+
}
72+
73+
74+
/* static public int minimizeMax(int[] nums, int p) {
75+
PriorityQueue<int[]> priorityQueue = new PriorityQueue<>((a, b) -> a[0] - b[0]);
76+
Arrays.sort(nums);
77+
for (int i = 1; i < nums.length; i++) {
78+
priorityQueue.add(new int[]{nums[i] - nums[i - 1], i - 1, i});
79+
}
80+
Set<Integer> set = new HashSet<>();
81+
int ans=0;
82+
while (p > 0) {
83+
int[] cur = priorityQueue.poll();
84+
if (!set.contains(cur[1]) && !set.contains(cur[2])) {
85+
set.add(cur[1]);
86+
set.add(cur[2]);
87+
ans=Math.max(cur[0],ans);
88+
int left=cur[1]-1;
89+
int right=cur[2]+1;
90+
if(left>=0&&right<nums.length){
91+
priorityQueue.add(new int[]{nums[right]-nums[left],left,right});
92+
}
93+
p--;
94+
}
95+
}
96+
return ans;
97+
}*/
98+
99+
100+
//最大化最小 考虑二分
101+
static public int minimizeMax(int[] nums, int p) {
102+
Arrays.sort(nums);
103+
int left = 0, right = nums[nums.length - 1] - nums[0];
104+
105+
while (left < right) {
106+
int mid = (left + right) / 2;
107+
if (check(nums, mid, p)) {
108+
right = mid;
109+
} else {
110+
left = mid + 1;
111+
}
112+
}
113+
return left;
114+
}
115+
116+
static boolean check(int[] nums, int mid, int p) {
117+
Deque<Integer> deque = new ArrayDeque<>();
118+
int ans = 0;
119+
for (int i = 0; i < nums.length; i++) {
120+
if (!deque.isEmpty()) {
121+
if (nums[i] - deque.peekLast() <= mid) {
122+
ans++;
123+
deque.pollLast();
124+
} else {
125+
deque.addLast(nums[i]);
126+
}
127+
} else {
128+
deque.addLast(nums[i]);
129+
}
130+
}
131+
return ans >= p;
132+
}
133+
134+
135+
//记录每次每行每列到达的最大位置
136+
public int minimumVisitedCells(int[][] grid) {
137+
Queue<int[]> queue = new LinkedList<>();
138+
queue.add(new int[]{0, 0});
139+
int m = grid.length;
140+
int n = grid[0].length;
141+
int[] maxBelow = new int[n];
142+
int[] maxRight = new int[m];
143+
144+
Set<Integer> set = new HashSet<>();
145+
int step = 1;
146+
set.add(0);
147+
while (!queue.isEmpty()) {
148+
int size = queue.size();
149+
while (size-- > 0) {
150+
int[] cur = queue.poll();
151+
if (cur[0] == m - 1 && cur[1] == n - 1) {
152+
return step;
153+
}
154+
int k = grid[cur[0]][cur[1]];
155+
156+
int belowM = Math.min(m - 1, cur[0] + k);
157+
int rightM = Math.min(n - 1, cur[1] + k);
158+
159+
160+
//取最大值,因为可能到不了cur[0]这个位置
161+
int begin=Math.max(maxBelow[cur[1]],cur[0]);
162+
for (int i = begin; i <= belowM; i++) {
163+
int nx = i, ny = cur[1];
164+
if(set.contains(nx * n + ny)) continue;
165+
set.add(nx * n + ny);
166+
queue.add(new int[]{nx, ny});
167+
}
168+
//取最大值,因为可能到不了cur[1]这个位置
169+
begin=Math.max(maxRight[cur[0]],cur[1]);
170+
for (int i = begin; i <= rightM; i++) {
171+
int nx = cur[0], ny = i;
172+
if(set.contains(nx * n + ny)) continue;
173+
set.add(nx * n + ny);
174+
queue.add(new int[]{nx, ny});
175+
}
176+
maxBelow[cur[1]]=Math.max(belowM,maxBelow[cur[1]]);
177+
maxRight[cur[0]]=Math.max(rightM,maxRight[cur[0]]);
178+
}
179+
step++;
180+
}
181+
return -1;
182+
}
183+
184+
public static void main(String[] args) {
185+
minimizeMax(new int[]{2, 4, 1, 2}, 1);
186+
}
187+
}

src/main/java/weekly/wk341.java

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
package weekly;
2+
3+
import sun.security.krb5.internal.APRep;
4+
5+
import java.util.ArrayList;
6+
import java.util.Arrays;
7+
import java.util.HashMap;
8+
import java.util.HashSet;
9+
import java.util.LinkedList;
10+
import java.util.List;
11+
import java.util.Map;
12+
import java.util.Queue;
13+
import java.util.Set;
14+
15+
public class wk341 {
16+
//模拟
17+
public int[] rowAndMaximumOnes(int[][] mat) {
18+
int ans = 0;
19+
int count = 0;
20+
for (int i = 0; i < mat.length; i++) {
21+
int c = 0;
22+
for (int j = 0; j < mat[0].length; j++) {
23+
if (mat[i][j] == 1) {
24+
c++;
25+
}
26+
}
27+
if (c > count) {
28+
count = c;
29+
ans = i;
30+
}
31+
}
32+
return new int[]{ans, count};
33+
}
34+
35+
36+
//枚举
37+
public int maxDivScore(int[] nums, int[] divisors) {
38+
int[] score = new int[divisors.length];
39+
for (int i = 0; i < divisors.length; i++) {
40+
int count = 0;
41+
for (int j = 0; j < nums.length; j++) {
42+
if (nums[j] % divisors[i] == 0) {
43+
count++;
44+
}
45+
}
46+
score[i] = count;
47+
}
48+
49+
int max = 0;
50+
int ans = Integer.MAX_VALUE;
51+
for (int i = 0; i < score.length; i++) {
52+
if (score[i] > max) {
53+
ans = divisors[i];
54+
max = score[i];
55+
} else if (score[i] == max && divisors[i] < ans) {
56+
ans = divisors[i];
57+
}
58+
}
59+
return ans;
60+
}
61+
62+
63+
//贪心,尽量用之前没有用完的字母
64+
static public int addMinimum(String word) {
65+
char pre = 'c';
66+
int ans = 0;
67+
68+
for (int i = 0; i < word.length(); i++) {
69+
char c = word.charAt(i);
70+
//前面结束
71+
if (pre == 'c') {
72+
ans += c - 'a';
73+
pre = c;
74+
} else {
75+
if (c > pre) {
76+
ans += c - pre - 1;
77+
pre = c;
78+
} else {
79+
//表示前面的需要结束,重新开始
80+
ans += 'c' - pre;
81+
pre = 'c';
82+
i--;
83+
}
84+
}
85+
}
86+
ans += 'c' - pre;
87+
return ans;
88+
}
89+
90+
//转换成count数组然后树形dp
91+
public int minimumTotalPrice(int n, int[][] edges, int[] price, int[][] trips) {
92+
Map<Integer, List<Integer>> map = new HashMap<>();
93+
for (int[] edge : edges) {
94+
if (!map.containsKey(edge[0])) map.put(edge[0], new ArrayList<>());
95+
if (!map.containsKey(edge[1])) map.put(edge[1], new ArrayList<>());
96+
map.get(edge[0]).add(edge[1]);
97+
map.get(edge[1]).add(edge[0]);
98+
}
99+
int[] count = new int[n];
100+
101+
for (int[] trip : trips) {
102+
dfs(map, count, trip[0], trip[1], -1);
103+
}
104+
105+
int[] ans = dfs2(map, count, price, 0, -1);
106+
return Math.min(ans[0], ans[1]);
107+
}
108+
109+
boolean dfs(Map<Integer, List<Integer>> map, int[] count, int cur, int target, int parent) {
110+
if (cur == target) {
111+
count[cur]++;
112+
return true;
113+
}
114+
115+
for (Integer next : map.getOrDefault(cur, new ArrayList<>())) {
116+
if (next == parent) continue;
117+
//是路径上的点
118+
if (dfs(map, count, next, target, cur)) {
119+
count[cur]++;
120+
return true;
121+
}
122+
}
123+
return false;
124+
}
125+
126+
int[] dfs2(Map<Integer, List<Integer>> map, int[] count, int[] price, int cur, int parent) {
127+
128+
int[] ans = new int[]{price[cur] * count[cur], price[cur] * count[cur]/2};
129+
130+
int childMaxSum = 0;
131+
int childNoSum = 0;
132+
for (Integer next : map.getOrDefault(cur, new ArrayList<>())) {
133+
if (next == parent) continue;
134+
int[] child = dfs2(map, count, price, next, cur);
135+
childMaxSum += Math.min(child[0], child[1]);
136+
childNoSum += child[0];
137+
}
138+
ans[0] += childMaxSum;
139+
ans[1] +=childNoSum;
140+
return ans;
141+
}
142+
143+
144+
public static void main(String[] args) {
145+
wk341 w = new wk341();
146+
w.minimumTotalPrice(4, new int[][]{{0, 1}, {1, 2}, {1, 3}}, new int[]{2, 2, 10, 6}, new int[][]{{0, 3}, {2, 1}, {2, 3}});
147+
}
148+
}

0 commit comments

Comments
 (0)