Skip to content

Commit 325a35e

Browse files
committed
834-1813-1814-1825 (4)
1 parent 12a275a commit 325a35e

File tree

10 files changed

+449
-7
lines changed

10 files changed

+449
-7
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import java.util.ArrayList;
2+
import java.util.HashMap;
3+
import java.util.List;
4+
import java.util.Map;
5+
6+
public class Solution834 {
7+
private Map<Integer, List<Integer>> adj;
8+
private int[] sz, dp, ans;
9+
10+
// https://leetcode.cn/problems/sum-of-distances-in-tree/solution/shu-zhong-ju-chi-zhi-he-by-leetcode-solution/
11+
public int[] sumOfDistancesInTree(int n, int[][] edges) {
12+
adj = new HashMap<>();
13+
for (int[] edge : edges) {
14+
adj.computeIfAbsent(edge[0], key -> new ArrayList<>()).add(edge[1]);
15+
adj.computeIfAbsent(edge[1], key -> new ArrayList<>()).add(edge[0]);
16+
}
17+
// dp[u] 表示以 u 为根的子树,它的所有子节点到它的距离之和
18+
// sz[u] 表示以 u 为根的子树的节点数量
19+
sz = new int[n];
20+
dp = new int[n];
21+
ans = new int[n];
22+
23+
dfs1(0, -1);
24+
dfs2(0, -1);
25+
return ans;
26+
}
27+
28+
private void dfs1(int u, int fa) {
29+
sz[u] = 1;
30+
dp[u] = 0;
31+
for (int v : adj.getOrDefault(u, new ArrayList<>())) {
32+
if (v == fa) {
33+
continue;
34+
}
35+
dfs1(v, u);
36+
dp[u] += dp[v] + sz[v];
37+
sz[u] += sz[v];
38+
}
39+
}
40+
41+
private void dfs2(int u, int fa) {
42+
ans[u] = dp[u];
43+
for (int v : adj.getOrDefault(u, new ArrayList<>())) {
44+
if (v == fa) {
45+
continue;
46+
}
47+
// 让 v 换到根的位置,u 变为其孩子节点,同时维护原有的 dp 信息
48+
int pu = dp[u], pv = dp[v];
49+
int su = sz[u], sv = sz[v];
50+
51+
dp[u] -= dp[v] + sz[v];
52+
sz[u] -= sz[v];
53+
dp[v] += dp[u] + sz[u];
54+
sz[v] += sz[u];
55+
56+
dfs2(v, u);
57+
58+
dp[u] = pu;
59+
dp[v] = pv;
60+
sz[u] = su;
61+
sz[v] = sv;
62+
}
63+
}
64+
}
65+
/*
66+
834. 树中距离之和
67+
https://leetcode.cn/problems/sum-of-distances-in-tree/
68+
69+
给定一个无向、连通的树。树中有 n 个标记为 0...n-1 的节点以及 n-1 条边 。
70+
给定整数 n 和数组 edges , edges[i] = [ai, bi]表示树中的节点 ai 和 bi 之间有一条边。
71+
返回长度为 n 的数组 answer ,其中 answer[i] 是树中第 i 个节点与所有其他节点之间的距离之和。
72+
提示:
73+
1 <= n <= 3 * 10^4
74+
edges.length == n - 1
75+
edges[i].length == 2
76+
0 <= ai, bi < n
77+
ai != bi
78+
给定的输入保证为有效的树
79+
80+
树形 DP
81+
官方题解: https://leetcode.cn/problems/sum-of-distances-in-tree/solution/shu-zhong-ju-chi-zhi-he-by-leetcode-solution/
82+
*/
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
public class Solution834Tests {
5+
private final Solution834 solution834 = new Solution834();
6+
7+
@Test
8+
public void example1() {
9+
int n = 6;
10+
int[][] edges = UtUtils.stringToInts2("[[0,1],[0,2],[2,3],[2,4],[2,5]]");
11+
int[] expected = {8, 12, 6, 10, 10, 10};
12+
Assertions.assertArrayEquals(expected, solution834.sumOfDistancesInTree(n, edges));
13+
}
14+
15+
@Test
16+
public void example2() {
17+
int n = 1;
18+
int[][] edges = UtUtils.stringToInts2("[]");
19+
int[] expected = {0};
20+
Assertions.assertArrayEquals(expected, solution834.sumOfDistancesInTree(n, edges));
21+
}
22+
23+
@Test
24+
public void example3() {
25+
int n = 2;
26+
int[][] edges = UtUtils.stringToInts2("[[1,0]]");
27+
int[] expected = {1, 1};
28+
Assertions.assertArrayEquals(expected, solution834.sumOfDistancesInTree(n, edges));
29+
}
30+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
public class Solution1813 {
2+
public boolean areSentencesSimilar(String sentence1, String sentence2) {
3+
String[] words1 = sentence1.split(" ");
4+
String[] words2 = sentence2.split(" ");
5+
int n = words1.length;
6+
int m = words2.length;
7+
// 最短长度
8+
int minLen = Math.min(n, m);
9+
10+
int i = 0;
11+
int j = 0;
12+
while (i < minLen && words1[i].equals(words2[i])) {
13+
i++;
14+
}
15+
while (i + j < minLen && words1[n - 1 - j].equals(words2[m - 1 - j])) {
16+
j++;
17+
}
18+
return i + j == minLen;
19+
}
20+
}
21+
/*
22+
1813. 句子相似性 III
23+
https://leetcode.cn/problems/sentence-similarity-iii/
24+
25+
一个句子是由一些单词与它们之间的单个空格组成,且句子的开头和结尾没有多余空格。比方说,"Hello World" ,"HELLO" ,"hello world hello world" 都是句子。每个单词都 只 包含大写和小写英文字母。
26+
如果两个句子 sentence1 和 sentence2 ,可以通过往其中一个句子插入一个任意的句子(可以是空句子)而得到另一个句子,那么我们称这两个句子是 相似的 。
27+
比方说,sentence1 = "Hello my name is Jane" 且 sentence2 = "Hello Jane" ,我们可以往 sentence2 中 "Hello" 和 "Jane" 之间插入 "my name is" 得到 sentence1 。
28+
给你两个句子 sentence1 和 sentence2 ,如果 sentence1 和 sentence2 是相似的,请你返回 true ,否则返回 false 。
29+
提示:
30+
1 <= sentence1.length, sentence2.length <= 100
31+
sentence1 和 sentence2 都只包含大小写英文字母和空格。
32+
sentence1 和 sentence2 中的单词都只由单个空格隔开。
33+
34+
双指针
35+
*/
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import java.util.HashMap;
2+
import java.util.Map;
3+
4+
public class Solution1814 {
5+
private static final int MOD = (int) (1e9 + 7);
6+
7+
public int countNicePairs(int[] nums) {
8+
Map<Long, Integer> cntMap = new HashMap<>();
9+
for (int num : nums) {
10+
long key = num - rev(num);
11+
cntMap.put(key, cntMap.getOrDefault(key, 0) + 1);
12+
}
13+
14+
long res = 0;
15+
for (long x : cntMap.values()) {
16+
res = (res + x * (x - 1) / 2) % MOD;
17+
}
18+
return (int) res;
19+
}
20+
21+
private long rev(int num) {
22+
return Long.parseLong(new StringBuilder(String.valueOf(num)).reverse().toString());
23+
}
24+
}
25+
/*
26+
1814. 统计一个数组中好对子的数目
27+
https://leetcode.cn/problems/count-nice-pairs-in-an-array/
28+
29+
给你一个数组 nums ,数组中只包含非负整数。定义 rev(x) 的值为将整数 x 各个数字位反转得到的结果。比方说 rev(123) = 321 , rev(120) = 21 。我们称满足下面条件的下标对 (i, j) 是 好的 :
30+
- 0 <= i < j < nums.length
31+
- nums[i] + rev(nums[j]) == nums[j] + rev(nums[i])
32+
请你返回好下标对的数目。由于结果可能会很大,请将结果对 109 + 7 取余 后返回。
33+
提示:
34+
1 <= nums.length <= 10^5
35+
0 <= nums[i] <= 10^9
36+
37+
HashMap + 计数
38+
*/
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
import java.util.LinkedList;
2+
import java.util.Queue;
3+
import java.util.TreeMap;
4+
5+
public class Solution1825 {
6+
static class MKAverage {
7+
private final int m;
8+
private final int k;
9+
private final Queue<Integer> queue;
10+
// 分别存储最小 k 个,中间,最大 k 个元素
11+
private final TreeMap<Integer, Integer> map1, map2, map3;
12+
// 三个 TreeMap 对应的 size
13+
private int sz1, sz2, sz3;
14+
// 容器剩余 m-2k 个元素的和
15+
private long sum;
16+
17+
public MKAverage(int m, int k) {
18+
this.m = m;
19+
this.k = k;
20+
queue = new LinkedList<>();
21+
map1 = new TreeMap<>();
22+
map2 = new TreeMap<>();
23+
map3 = new TreeMap<>();
24+
sz1 = 0;
25+
sz2 = 0;
26+
sz3 = 0;
27+
sum = 0L;
28+
}
29+
30+
public void addElement(int num) {
31+
queue.add(num);
32+
if (queue.size() <= m) {
33+
map2add(num);
34+
if (queue.size() == m) {
35+
while (sz1 < k) {
36+
int min = map2.firstKey();
37+
map2del(min);
38+
map1add(min);
39+
}
40+
while (sz3 < k) {
41+
int max = map2.lastKey();
42+
map2del(max);
43+
map3add(max);
44+
}
45+
}
46+
return;
47+
}
48+
49+
// q 的元素数目等于 m+1
50+
if (num < map1.lastKey()) {
51+
map1add(num);
52+
int max = map1.lastKey();
53+
map1del(max);
54+
map2add(max);
55+
} else if (num > map3.firstKey()) {
56+
map3add(num);
57+
int min = map3.firstKey();
58+
map3del(min);
59+
map2add(min);
60+
} else {
61+
map2add(num);
62+
}
63+
64+
int rm = queue.remove();
65+
if (map1.containsKey(rm)) {
66+
map1del(rm);
67+
int min = map2.firstKey();
68+
map2del(min);
69+
map1add(min);
70+
} else if (map3.containsKey(rm)) {
71+
map3del(rm);
72+
int max = map2.lastKey();
73+
map2del(max);
74+
map3add(max);
75+
} else {
76+
map2del(rm);
77+
}
78+
}
79+
80+
public int calculateMKAverage() {
81+
if (queue.size() < m) {
82+
return -1;
83+
}
84+
return (int) (sum / (m - k - k));
85+
}
86+
87+
// 封装 "原子操作"
88+
private void map1del(int num) {
89+
int val = map1.get(num);
90+
if (val - 1 == 0) {
91+
map1.remove(num);
92+
} else {
93+
map1.put(num, val - 1);
94+
}
95+
sz1--;
96+
}
97+
98+
private void map2del(int num) {
99+
int val = map2.get(num);
100+
if (val - 1 == 0) {
101+
map2.remove(num);
102+
} else {
103+
map2.put(num, val - 1);
104+
}
105+
sz2--;
106+
sum -= num;
107+
}
108+
109+
private void map3del(int num) {
110+
int val = map3.get(num);
111+
if (val - 1 == 0) {
112+
map3.remove(num);
113+
} else {
114+
map3.put(num, val - 1);
115+
}
116+
sz3--;
117+
}
118+
119+
private void map1add(int num) {
120+
map1.put(num, map1.getOrDefault(num, 0) + 1);
121+
sz1++;
122+
}
123+
124+
private void map2add(int num) {
125+
map2.put(num, map2.getOrDefault(num, 0) + 1);
126+
sz2++;
127+
sum += num;
128+
}
129+
130+
private void map3add(int num) {
131+
map3.put(num, map3.getOrDefault(num, 0) + 1);
132+
sz3++;
133+
}
134+
}
135+
}
136+
/*
137+
1825. 求出 MK 平均值
138+
https://leetcode.cn/problems/finding-mk-average/
139+
140+
给你两个整数 m 和 k ,以及数据流形式的若干整数。你需要实现一个数据结构,计算这个数据流的 MK 平均值 。
141+
MK 平均值 按照如下步骤计算:
142+
1. 如果数据流中的整数少于 m 个,MK 平均值 为 -1 ,否则将数据流中最后 m 个元素拷贝到一个独立的容器中。
143+
2. 从这个容器中删除最小的 k 个数和最大的 k 个数。
144+
3. 计算剩余元素的平均值,并 向下取整到最近的整数 。
145+
请你实现 MKAverage 类:
146+
- MKAverage(int m, int k) 用一个空的数据流和两个整数 m 和 k 初始化 MKAverage 对象。
147+
- void addElement(int num) 往数据流中插入一个新的元素 num 。
148+
- int calculateMKAverage() 对当前的数据流计算并返回 MK 平均数 ,结果需 向下取整到最近的整数 。
149+
提示:
150+
3 <= m <= 10^5
151+
1 <= k*2 < m
152+
1 <= num <= 10^5
153+
addElement 与 calculateMKAverage 总操作次数不超过 10^5 次。
154+
155+
队列 + 三个 TreeMap 模拟
156+
*/
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import org.junit.jupiter.api.Assertions;
2+
import org.junit.jupiter.api.Test;
3+
4+
public class Solution1813Tests {
5+
private final Solution1813 solution1813 = new Solution1813();
6+
7+
@Test
8+
public void example1() {
9+
String sentence1 = "My name is Haley";
10+
String sentence2 = "My Haley";
11+
Assertions.assertTrue(solution1813.areSentencesSimilar(sentence1, sentence2));
12+
}
13+
14+
@Test
15+
public void example2() {
16+
String sentence1 = "of";
17+
String sentence2 = "A lot of words";
18+
Assertions.assertFalse(solution1813.areSentencesSimilar(sentence1, sentence2));
19+
}
20+
21+
@Test
22+
public void example3() {
23+
String sentence1 = "Eating right now";
24+
String sentence2 = "Eating";
25+
Assertions.assertTrue(solution1813.areSentencesSimilar(sentence1, sentence2));
26+
}
27+
28+
@Test
29+
public void example4() {
30+
String sentence1 = "Luky";
31+
String sentence2 = "Lucccky";
32+
Assertions.assertFalse(solution1813.areSentencesSimilar(sentence1, sentence2));
33+
}
34+
}

0 commit comments

Comments
 (0)