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 9488df8

Browse files
feat: add solutions to lc problems: No.0813,0814 (doocs#3404)
* No.0813.Largest Sum of Averages * No.0814.Binary Tree Pruning
1 parent 495c6df commit 9488df8

File tree

18 files changed

+629
-133
lines changed

18 files changed

+629
-133
lines changed

‎solution/0800-0899/0813.Largest Sum of Averages/README.md‎

Lines changed: 207 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ tags:
3131
<pre>
3232
<strong>输入:</strong> nums = [9,1,2,3,9], k = 3
3333
<strong>输出:</strong> 20.00000
34-
<strong>解释:</strong>
35-
nums 的最优分组是[9], [1, 2, 3], [9]. 得到的分数是 9 + (1 + 2 + 3) / 3 + 9 = 20.
36-
我们也可以把 nums 分成[9, 1], [2], [3, 9].
34+
<strong>解释:</strong>
35+
nums 的最优分组是[9], [1, 2, 3], [9]. 得到的分数是 9 + (1 + 2 + 3) / 3 + 9 = 20.
36+
我们也可以把 nums 分成[9, 1], [2], [3, 9].
3737
这样的分组得到的分数为 5 + 2 + 6 = 13, 但不是最大值.
3838
</pre>
3939

@@ -64,17 +64,17 @@ nums 的最优分组是[9], [1, 2, 3], [9]. 得到的分数是 9 + (1 + 2 + 3) /
6464

6565
我们可以先预处理得到前缀和数组 $s,ドル方便快速得到子数组的和。
6666

67-
然后设计一个函数 $dfs(i, k),ドル表示从数组下标 $i$ 开始,最多分成 $k$ 组的最大平均值和。答案为 $dfs(0, k)$。函数 $dfs(i, k)$ 的执行逻辑如下:
67+
接下来,我们设计一个函数 $\textit{dfs}(i, k),ドル表示从数组下标 $i$ 开始,最多分成 $k$ 组的最大平均值和。答案为 $\textit{dfs}(0, k)$。
6868

69-
当 $i=n$ 时,表示已经遍历到数组末尾,此时返回 0ドル$。
69+
函数 $\textit{dfs}(i, k)$ 的执行逻辑如下:
7070

71-
当 $k=1$ 时,表示只剩下一组,此时返回从下标 $i$ 开始到数组末尾的平均值
71+
当 $i = n$ 时,表示已经遍历到数组末尾,此时返回 0ドル$
7272

73-
否则,我们在 $[i, ..n-1]$ 的范围内枚举分组的结束位置 $j,ドル计算从下标 $i$ 到下标 $j$ 的平均值,以及从下标 $j+1$ 开始,最多分成 $k-1$ 组的最大平均值和。取其中的最大值作为答案
73+
当 $k = 1$ 时,表示只剩下一组,此时返回从下标 $i$ 开始到数组末尾的平均值
7474

75-
为了避免重复计算,我们可以用数组 $f$ 记忆化函数 $dfs(i, k)$ 的返回值
75+
否则,我们在 $[i + 1, n)$ 的区间内枚举下一个分组的开始位置 $j,ドル计算从 $i$ 到 $j - 1$ 的平均值 $\frac{s[j] - s[i]}{j - i},ドル加上 $\textit{dfs}(j, k - 1)$ 的结果,取所有结果的最大值
7676

77-
时间复杂度 $O(n^2 \times k),ドル空间复杂度 $O(n \times k)$。其中 $n$ 表示数组 `nums` 的长度。
77+
时间复杂度 $O(n^2 \times k),ドル空间复杂度 $O(n \times k)$。其中 $n$ 表示数组 $\textit{nums}$ 的长度。
7878

7979
<!-- tabs:start -->
8080

@@ -84,15 +84,14 @@ nums 的最优分组是[9], [1, 2, 3], [9]. 得到的分数是 9 + (1 + 2 + 3) /
8484
class Solution:
8585
def largestSumOfAverages(self, nums: List[int], k: int) -> float:
8686
@cache
87-
def dfs(i, k):
87+
def dfs(i: int, k: int) -> float:
8888
if i == n:
8989
return 0
9090
if k == 1:
91-
return (s[-1] - s[i]) / (n - i)
91+
return (s[n] - s[i]) / (n - i)
9292
ans = 0
93-
for j in range(i, n):
94-
t = (s[j + 1] - s[i]) / (j - i + 1) + dfs(j + 1, k - 1)
95-
ans = max(ans, t)
93+
for j in range(i + 1, n):
94+
ans = max(ans, (s[j] - s[i]) / (j - i) + dfs(j, k - 1))
9695
return ans
9796

9897
n = len(nums)
@@ -111,7 +110,7 @@ class Solution {
111110
public double largestSumOfAverages(int[] nums, int k) {
112111
n = nums.length;
113112
s = new int[n + 1];
114-
f = new Double[n+1][k + 1];
113+
f = new Double[n][k + 1];
115114
for (int i = 0; i < n; ++i) {
116115
s[i + 1] = s[i] + nums[i];
117116
}
@@ -129,9 +128,8 @@ class Solution {
129128
return f[i][k];
130129
}
131130
double ans = 0;
132-
for (int j = i; j < n; ++j) {
133-
double t = (s[j + 1] - s[i]) * 1.0 / (j - i + 1) + dfs(j + 1, k - 1);
134-
ans = Math.max(ans, t);
131+
for (int j = i + 1; j < n; ++j) {
132+
ans = Math.max(ans, (s[j] - s[i]) * 1.0 /(j - i) + dfs(j, k - 1));
135133
}
136134
return f[i][k] = ans;
137135
}
@@ -147,21 +145,28 @@ public:
147145
int n = nums.size();
148146
int s[n + 1];
149147
double f[n][k + 1];
148+
memset(f, 0, sizeof(f));
150149
s[0] = 0;
151-
memset(f, 0, sizeof f);
152-
for (int i = 0; i < n; ++i) s[i + 1] = s[i] + nums[i];
153-
function<double(int, int)> dfs = [&](int i, int k) -> double {
154-
if (i == n) return 0;
155-
if (k == 1) return (s[n] - s[i]) * 1.0 / (n - i);
156-
if (f[i][k]) return f[i][k];
150+
for (int i = 0; i < n; ++i) {
151+
s[i + 1] = s[i] + nums[i];
152+
}
153+
auto dfs = [&](auto&& dfs, int i, int k) -> double {
154+
if (i == n) {
155+
return 0;
156+
}
157+
if (k == 1) {
158+
return (s[n] - s[i]) * 1.0 / (n - i);
159+
}
160+
if (f[i][k] > 0) {
161+
return f[i][k];
162+
}
157163
double ans = 0;
158-
for (int j = i; j < n; ++j) {
159-
double t = (s[j + 1] - s[i]) * 1.0 / (j - i + 1) + dfs(j + 1, k - 1);
160-
ans = max(ans, t);
164+
for (int j = i + 1; j < n; ++j) {
165+
ans = max(ans, (s[j] - s[i]) * 1.0 / (j - i) + dfs(dfs, j, k - 1));
161166
}
162167
return f[i][k] = ans;
163168
};
164-
return dfs(0, k);
169+
return dfs(dfs, 0, k);
165170
}
166171
};
167172
```
@@ -172,25 +177,27 @@ public:
172177
func largestSumOfAverages(nums []int, k int) float64 {
173178
n := len(nums)
174179
s := make([]int, n+1)
175-
f := [110][110]float64{}
176-
for i, v := range nums {
177-
s[i+1] = s[i] + v
180+
for i, x := range nums {
181+
s[i+1] = s[i] + x
178182
}
179-
var dfs func(i, k int) float64
183+
f := make([][]float64, n)
184+
for i := range f {
185+
f[i] = make([]float64, k+1)
186+
}
187+
var dfs func(int, int) float64
180188
dfs = func(i, k int) float64 {
181189
if i == n {
182190
return 0
183191
}
184-
if k == 1 {
185-
return float64(s[n]-s[i]) / float64(n-i)
186-
}
187192
if f[i][k] > 0 {
188193
return f[i][k]
189194
}
190-
var ans float64
191-
for j := i; j < n; j++ {
192-
t := float64(s[j+1]-s[i])/float64(j-i+1) + dfs(j+1, k-1)
193-
ans = math.Max(ans, t)
195+
if k == 1 {
196+
return float64(s[n]-s[i]) / float64(n-i)
197+
}
198+
ans := 0.0
199+
for j := i + 1; j < n; j++ {
200+
ans = math.Max(ans, float64(s[j]-s[i])/float64(j-i)+dfs(j, k-1))
194201
}
195202
f[i][k] = ans
196203
return ans
@@ -199,6 +206,167 @@ func largestSumOfAverages(nums []int, k int) float64 {
199206
}
200207
```
201208

209+
#### TypeScript
210+
211+
```ts
212+
function largestSumOfAverages(nums: number[], k: number): number {
213+
const n = nums.length;
214+
const s: number[] = Array(n + 1).fill(0);
215+
for (let i = 0; i < n; i++) {
216+
s[i + 1] = s[i] + nums[i];
217+
}
218+
const f: number[][] = Array.from({ length: n }, () => Array(k + 1).fill(0));
219+
const dfs = (i: number, k: number): number => {
220+
if (i === n) {
221+
return 0;
222+
}
223+
if (f[i][k] > 0) {
224+
return f[i][k];
225+
}
226+
if (k === 1) {
227+
return (s[n] - s[i]) / (n - i);
228+
}
229+
for (let j = i + 1; j < n; j++) {
230+
f[i][k] = Math.max(f[i][k], dfs(j, k - 1) + (s[j] - s[i]) / (j - i));
231+
}
232+
return f[i][k];
233+
};
234+
return dfs(0, k);
235+
}
236+
```
237+
238+
<!-- tabs:end -->
239+
240+
<!-- solution:end -->
241+
242+
<!-- solution:start -->
243+
244+
### 方法二:动态规划
245+
246+
我们可以将方法一的记忆化搜索转化为动态规划。
247+
248+
定义 $f[i][j]$ 表示数组 $\textit{nums}$ 的前 $i$ 个元素最多分成 $j$ 组的最大平均值和。答案为 $f[n][k]$。
249+
250+
对于 $f[i][j],ドル我们可以枚举上一组的结束位置 $h,ドル计算 $f[h][j-1],ドル加上 $\frac{s[i]-s[h]}{i-h}$ 的结果,取所有结果的最大值。
251+
252+
时间复杂度 $O(n^2 \times k),ドル空间复杂度 $O(n \times k)$。其中 $n$ 表示数组 $\textit{nums}$ 的长度。
253+
254+
<!-- tabs:start -->
255+
256+
#### Python3
257+
258+
```python
259+
class Solution:
260+
def largestSumOfAverages(self, nums: List[int], k: int) -> float:
261+
n = len(nums)
262+
f = [[0] * (k + 1) for _ in range(n + 1)]
263+
s = list(accumulate(nums, initial=0))
264+
for i in range(1, n + 1):
265+
f[i][1] = s[i] / i
266+
for j in range(2, min(i + 1, k + 1)):
267+
for h in range(i):
268+
f[i][j] = max(f[i][j], f[h][j - 1] + (s[i] - s[h]) / (i - h))
269+
return f[n][k]
270+
```
271+
272+
#### Java
273+
274+
```java
275+
class Solution {
276+
public double largestSumOfAverages(int[] nums, int k) {
277+
int n = nums.length;
278+
double[][] f = new double[n + 1][k + 1];
279+
int[] s = new int[n + 1];
280+
for (int i = 0; i < n; ++i) {
281+
s[i + 1] = s[i] + nums[i];
282+
}
283+
for (int i = 1; i <= n; ++i) {
284+
f[i][1] = s[i] * 1.0 / i;
285+
for (int j = 2; j <= Math.min(i, k); ++j) {
286+
for (int h = 0; h < i; ++h) {
287+
f[i][j] = Math.max(f[i][j], f[h][j - 1] + (s[i] - s[h]) * 1.0 / (i - h));
288+
}
289+
}
290+
}
291+
return f[n][k];
292+
}
293+
}
294+
```
295+
296+
#### C++
297+
298+
```cpp
299+
class Solution {
300+
public:
301+
double largestSumOfAverages(vector<int>& nums, int k) {
302+
int n = nums.size();
303+
int s[n + 1];
304+
s[0] = 0;
305+
double f[n + 1][k + 1];
306+
memset(f, 0, sizeof(f));
307+
for (int i = 0; i < n; ++i) {
308+
s[i + 1] = s[i] + nums[i];
309+
}
310+
for (int i = 1; i <= n; ++i) {
311+
f[i][1] = s[i] * 1.0 / i;
312+
for (int j = 2; j <= min(i, k); ++j) {
313+
for (int h = 0; h < i; ++h) {
314+
f[i][j] = max(f[i][j], f[h][j - 1] + (s[i] - s[h]) * 1.0 / (i - h));
315+
}
316+
}
317+
}
318+
return f[n][k];
319+
}
320+
};
321+
```
322+
323+
#### Go
324+
325+
```go
326+
func largestSumOfAverages(nums []int, k int) float64 {
327+
n := len(nums)
328+
s := make([]int, n+1)
329+
for i, x := range nums {
330+
s[i+1] = s[i] + x
331+
}
332+
f := make([][]float64, n+1)
333+
for i := range f {
334+
f[i] = make([]float64, k+1)
335+
}
336+
for i := 1; i <= n; i++ {
337+
f[i][1] = float64(s[i]) / float64(i)
338+
for j := 2; j <= min(i, k); j++ {
339+
for h := 0; h < i; h++ {
340+
f[i][j] = max(f[i][j], f[h][j-1]+float64(s[i]-s[h])/float64(i-h))
341+
}
342+
}
343+
}
344+
return f[n][k]
345+
}
346+
```
347+
348+
#### TypeScript
349+
350+
```ts
351+
function largestSumOfAverages(nums: number[], k: number): number {
352+
const n = nums.length;
353+
const s: number[] = Array(n + 1).fill(0);
354+
for (let i = 0; i < n; i++) {
355+
s[i + 1] = s[i] + nums[i];
356+
}
357+
const f: number[][] = Array.from({ length: n + 1 }, () => Array(k + 1).fill(0));
358+
for (let i = 1; i <= n; ++i) {
359+
f[i][1] = s[i] / i;
360+
for (let j = 2; j <= Math.min(i, k); ++j) {
361+
for (let h = 0; h < i; ++h) {
362+
f[i][j] = Math.max(f[i][j], f[h][j - 1] + (s[i] - s[h]) / (i - h));
363+
}
364+
}
365+
}
366+
return f[n][k];
367+
}
368+
```
369+
202370
<!-- tabs:end -->
203371

204372
<!-- solution:end -->

0 commit comments

Comments
(0)

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