Skip to content

feat: add solutions to lc problem: No.2920 #1949

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@

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

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

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,34 +61,204 @@

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

**方法一:记忆化搜索**

我们先根据题目给定的边构建图 $g$,其中 $g[i]$ 表示节点 $i$ 的所有邻接节点。然后我们可以使用记忆化搜索的方法求解本题。

我们设计一个函数 $dfs(i, fa, j)$,表示当前节点为 $i$,父节点为 $fa$,当前节点的金币数需要右移 $j$ 位,所能获得的最大积分。

函数 $dfs(i, fa, j)$ 的执行过程如下:

如果我们使用第一种方法收集当前节点的金币,那么当前节点的积分为 $(coins[i] >> j) - k$,然后我们遍历当前节点的所有邻接节点 $c$,如果 $c$ 不等于 $fa$,那么我们将 $dfs(c, i, j)$ 的结果累加到当前节点的积分中。

如果我们使用第二种方法收集当前节点的金币,那么当前节点的积分为 $coins[i] >> (j + 1)$,然后我们遍历当前节点的所有邻接节点 $c$,如果 $c$ 不等于 $fa$,那么我们将 $dfs(c, i, j + 1)$ 的结果累加到当前节点的积分中。注意,由于题目中给定的 $coins[i]$ 最大值为 $10^4$,因此我们最多只能右移 $14$ 位,就使得 $coins[i] >> (j + 1)$ 的值为 $0$。

最后,我们返回当前节点使用两种方法中能获得的最大积分。

为了避免重复计算,我们使用记忆化搜索的方法,将 $dfs(i, fa, j)$ 的结果存储到 $f[i][j]$ 中,其中 $f[i][j]$ 表示当前节点为 $i$,父节点为 $fa$,当前节点的金币数需要右移 $j$ 位,所能获得的最大积分。

时间复杂度 $O(n \times \log M)$,空间复杂度 $O(n \times \log M)$。其中 $M$ 表示 $coins[i]$ 的最大值。

<!-- tabs:start -->

### **Python3**

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

```python

class Solution:
def maximumPoints(self, edges: List[List[int]], coins: List[int], k: int) -> int:
@cache
def dfs(i: int, fa: int, j: int) -> int:
a = (coins[i] >> j) - k
b = coins[i] >> (j + 1)
for c in g[i]:
if c != fa:
a += dfs(c, i, j)
if j < 14:
b += dfs(c, i, j + 1)
return max(a, b)

n = len(coins)
g = [[] for _ in range(n)]
for a, b in edges:
g[a].append(b)
g[b].append(a)
ans = dfs(0, -1, 0)
dfs.cache_clear()
return ans
```

### **Java**

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

```java

class Solution {
private int k;
private int[] coins;
private Integer[][] f;
private List<Integer>[] g;

public int maximumPoints(int[][] edges, int[] coins, int k) {
this.k = k;
this.coins = coins;
int n = coins.length;
f = new Integer[n][15];
g = new List[n];
Arrays.setAll(g, i -> new ArrayList<>());
for (var e : edges) {
int a = e[0], b = e[1];
g[a].add(b);
g[b].add(a);
}
return dfs(0, -1, 0);
}

private int dfs(int i, int fa, int j) {
if (f[i][j] != null) {
return f[i][j];
}
int a = (coins[i] >> j) - k;
int b = coins[i] >> (j + 1);
for (int c : g[i]) {
if (c != fa) {
a += dfs(c, i, j);
if (j < 14) {
b += dfs(c, i, j + 1);
}
}
}
return f[i][j] = Math.max(a, b);
}
}
```

### **C++**

```cpp

class Solution {
public:
int maximumPoints(vector<vector<int>>& edges, vector<int>& coins, int k) {
int n = coins.size();
int f[n][15];
memset(f, -1, sizeof(f));
vector<int> g[n];
for (auto& e : edges) {
int a = e[0], b = e[1];
g[a].emplace_back(b);
g[b].emplace_back(a);
}
function<int(int, int, int)> dfs = [&](int i, int fa, int j) {
if (f[i][j] != -1) {
return f[i][j];
}
int a = (coins[i] >> j) - k;
int b = coins[i] >> (j + 1);
for (int c : g[i]) {
if (c != fa) {
a += dfs(c, i, j);
if (j < 14) {
b += dfs(c, i, j + 1);
}
}
}
return f[i][j] = max(a, b);
};
return dfs(0, -1, 0);
}
};
```

### **Go**

```go
func maximumPoints(edges [][]int, coins []int, k int) int {
n := len(coins)
f := make([][]int, n)
for i := range f {
f[i] = make([]int, 15)
for j := range f[i] {
f[i][j] = -1
}
}
g := make([][]int, n)
for _, e := range edges {
a, b := e[0], e[1]
g[a] = append(g[a], b)
g[b] = append(g[b], a)
}
var dfs func(int, int, int) int
dfs = func(i, fa, j int) int {
if f[i][j] != -1 {
return f[i][j]
}
a := (coins[i] >> j) - k
b := coins[i] >> (j + 1)
for _, c := range g[i] {
if c != fa {
a += dfs(c, i, j)
if j < 14 {
b += dfs(c, i, j+1)
}
}
}
f[i][j] = max(a, b)
return f[i][j]
}
return dfs(0, -1, 0)
}
```

### **TypeScript**

```ts
function maximumPoints(edges: number[][], coins: number[], k: number): number {
const n = coins.length;
const f: number[][] = Array.from({ length: n }, () => Array(15).fill(-1));
const g: number[][] = Array.from({ length: n }, () => []);
for (const [a, b] of edges) {
g[a].push(b);
g[b].push(a);
}
const dfs = (i: number, fa: number, j: number): number => {
if (f[i][j] !== -1) {
return f[i][j];
}
let a = (coins[i] >> j) - k;
let b = coins[i] >> (j + 1);
for (const c of g[i]) {
if (c !== fa) {
a += dfs(c, i, j);
if (j < 14) {
b += dfs(c, i, j + 1);
}
}
}
return (f[i][j] = Math.max(a, b));
};
return dfs(0, -1, 0);
}
```

### **...**
Expand Down
Loading