Skip to content

Commit b13d51e

Browse files
authoredNov 10, 2023
feat: add solutions to lc problem: No.2920 (#1949)
No.2920.Maximum Points After Collecting Coins From All Nodes
1 parent 60c216e commit b13d51e

File tree

8 files changed

+496
-5
lines changed

8 files changed

+496
-5
lines changed
 

‎solution/2300-2399/2300.Successful Pairs of Spells and Potions/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454

5555
**方法一:排序 + 二分查找**
5656

57-
我们可以对药水数组进行排序,然后遍历咒语数组,对于每个咒语,利用二分查找找到第一个大于等于 `success / v` 的药水,下标记为 $i$,那么药水的长度减去 $i$ 即为能跟该咒语成功组合的药水数目。
57+
我们可以对药水数组进行排序,然后遍历咒语数组,对于每个咒语 $v$,利用二分查找找到第一个大于等于 $\frac{success}{v}$ 的药水,下标记为 $i$,那么药水的长度减去 $i$ 即为能跟该咒语成功组合的药水数目。
5858

5959
时间复杂度 $O((m + n) \times \log m)$,空间复杂度 $O(\log n)$。其中 $m$ 和 $n$ 分别为药水数组和咒语数组的长度。
6060

‎solution/2900-2999/2920.Maximum Points After Collecting Coins From All Nodes/README.md

+173-3
Original file line numberDiff line numberDiff line change
@@ -61,34 +61,204 @@
6161

6262
<!-- 这里可写通用的实现逻辑 -->
6363

64+
**方法一:记忆化搜索**
65+
66+
我们先根据题目给定的边构建图 $g$,其中 $g[i]$ 表示节点 $i$ 的所有邻接节点。然后我们可以使用记忆化搜索的方法求解本题。
67+
68+
我们设计一个函数 $dfs(i, fa, j)$,表示当前节点为 $i$,父节点为 $fa$,当前节点的金币数需要右移 $j$ 位,所能获得的最大积分。
69+
70+
函数 $dfs(i, fa, j)$ 的执行过程如下:
71+
72+
如果我们使用第一种方法收集当前节点的金币,那么当前节点的积分为 $(coins[i] >> j) - k$,然后我们遍历当前节点的所有邻接节点 $c$,如果 $c$ 不等于 $fa$,那么我们将 $dfs(c, i, j)$ 的结果累加到当前节点的积分中。
73+
74+
如果我们使用第二种方法收集当前节点的金币,那么当前节点的积分为 $coins[i] >> (j + 1)$,然后我们遍历当前节点的所有邻接节点 $c$,如果 $c$ 不等于 $fa$,那么我们将 $dfs(c, i, j + 1)$ 的结果累加到当前节点的积分中。注意,由于题目中给定的 $coins[i]$ 最大值为 $10^4$,因此我们最多只能右移 $14$ 位,就使得 $coins[i] >> (j + 1)$ 的值为 $0$。
75+
76+
最后,我们返回当前节点使用两种方法中能获得的最大积分。
77+
78+
为了避免重复计算,我们使用记忆化搜索的方法,将 $dfs(i, fa, j)$ 的结果存储到 $f[i][j]$ 中,其中 $f[i][j]$ 表示当前节点为 $i$,父节点为 $fa$,当前节点的金币数需要右移 $j$ 位,所能获得的最大积分。
79+
80+
时间复杂度 $O(n \times \log M)$,空间复杂度 $O(n \times \log M)$。其中 $M$ 表示 $coins[i]$ 的最大值。
81+
6482
<!-- tabs:start -->
6583

6684
### **Python3**
6785

6886
<!-- 这里可写当前语言的特殊实现逻辑 -->
6987

7088
```python
71-
89+
class Solution:
90+
def maximumPoints(self, edges: List[List[int]], coins: List[int], k: int) -> int:
91+
@cache
92+
def dfs(i: int, fa: int, j: int) -> int:
93+
a = (coins[i] >> j) - k
94+
b = coins[i] >> (j + 1)
95+
for c in g[i]:
96+
if c != fa:
97+
a += dfs(c, i, j)
98+
if j < 14:
99+
b += dfs(c, i, j + 1)
100+
return max(a, b)
101+
102+
n = len(coins)
103+
g = [[] for _ in range(n)]
104+
for a, b in edges:
105+
g[a].append(b)
106+
g[b].append(a)
107+
ans = dfs(0, -1, 0)
108+
dfs.cache_clear()
109+
return ans
72110
```
73111

74112
### **Java**
75113

76114
<!-- 这里可写当前语言的特殊实现逻辑 -->
77115

78116
```java
79-
117+
class Solution {
118+
private int k;
119+
private int[] coins;
120+
private Integer[][] f;
121+
private List<Integer>[] g;
122+
123+
public int maximumPoints(int[][] edges, int[] coins, int k) {
124+
this.k = k;
125+
this.coins = coins;
126+
int n = coins.length;
127+
f = new Integer[n][15];
128+
g = new List[n];
129+
Arrays.setAll(g, i -> new ArrayList<>());
130+
for (var e : edges) {
131+
int a = e[0], b = e[1];
132+
g[a].add(b);
133+
g[b].add(a);
134+
}
135+
return dfs(0, -1, 0);
136+
}
137+
138+
private int dfs(int i, int fa, int j) {
139+
if (f[i][j] != null) {
140+
return f[i][j];
141+
}
142+
int a = (coins[i] >> j) - k;
143+
int b = coins[i] >> (j + 1);
144+
for (int c : g[i]) {
145+
if (c != fa) {
146+
a += dfs(c, i, j);
147+
if (j < 14) {
148+
b += dfs(c, i, j + 1);
149+
}
150+
}
151+
}
152+
return f[i][j] = Math.max(a, b);
153+
}
154+
}
80155
```
81156

82157
### **C++**
83158

84159
```cpp
85-
160+
class Solution {
161+
public:
162+
int maximumPoints(vector<vector<int>>& edges, vector<int>& coins, int k) {
163+
int n = coins.size();
164+
int f[n][15];
165+
memset(f, -1, sizeof(f));
166+
vector<int> g[n];
167+
for (auto& e : edges) {
168+
int a = e[0], b = e[1];
169+
g[a].emplace_back(b);
170+
g[b].emplace_back(a);
171+
}
172+
function<int(int, int, int)> dfs = [&](int i, int fa, int j) {
173+
if (f[i][j] != -1) {
174+
return f[i][j];
175+
}
176+
int a = (coins[i] >> j) - k;
177+
int b = coins[i] >> (j + 1);
178+
for (int c : g[i]) {
179+
if (c != fa) {
180+
a += dfs(c, i, j);
181+
if (j < 14) {
182+
b += dfs(c, i, j + 1);
183+
}
184+
}
185+
}
186+
return f[i][j] = max(a, b);
187+
};
188+
return dfs(0, -1, 0);
189+
}
190+
};
86191
```
87192
88193
### **Go**
89194
90195
```go
196+
func maximumPoints(edges [][]int, coins []int, k int) int {
197+
n := len(coins)
198+
f := make([][]int, n)
199+
for i := range f {
200+
f[i] = make([]int, 15)
201+
for j := range f[i] {
202+
f[i][j] = -1
203+
}
204+
}
205+
g := make([][]int, n)
206+
for _, e := range edges {
207+
a, b := e[0], e[1]
208+
g[a] = append(g[a], b)
209+
g[b] = append(g[b], a)
210+
}
211+
var dfs func(int, int, int) int
212+
dfs = func(i, fa, j int) int {
213+
if f[i][j] != -1 {
214+
return f[i][j]
215+
}
216+
a := (coins[i] >> j) - k
217+
b := coins[i] >> (j + 1)
218+
for _, c := range g[i] {
219+
if c != fa {
220+
a += dfs(c, i, j)
221+
if j < 14 {
222+
b += dfs(c, i, j+1)
223+
}
224+
}
225+
}
226+
f[i][j] = max(a, b)
227+
return f[i][j]
228+
}
229+
return dfs(0, -1, 0)
230+
}
231+
```
91232

233+
### **TypeScript**
234+
235+
```ts
236+
function maximumPoints(edges: number[][], coins: number[], k: number): number {
237+
const n = coins.length;
238+
const f: number[][] = Array.from({ length: n }, () => Array(15).fill(-1));
239+
const g: number[][] = Array.from({ length: n }, () => []);
240+
for (const [a, b] of edges) {
241+
g[a].push(b);
242+
g[b].push(a);
243+
}
244+
const dfs = (i: number, fa: number, j: number): number => {
245+
if (f[i][j] !== -1) {
246+
return f[i][j];
247+
}
248+
let a = (coins[i] >> j) - k;
249+
let b = coins[i] >> (j + 1);
250+
for (const c of g[i]) {
251+
if (c !== fa) {
252+
a += dfs(c, i, j);
253+
if (j < 14) {
254+
b += dfs(c, i, j + 1);
255+
}
256+
}
257+
}
258+
return (f[i][j] = Math.max(a, b));
259+
};
260+
return dfs(0, -1, 0);
261+
}
92262
```
93263

94264
### **...**

0 commit comments

Comments
 (0)