From 34903dd87926a6935720fdb0a1d0fc196cda9bd7 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Mon, 12 Aug 2024 20:00:22 +0800 Subject: [PATCH 1/2] feat: add solutions to lc problem: No.0813 No.0813.Largest Sum of Averages --- .../0813.Largest Sum of Averages/README.md | 246 +++++++++++++++--- .../0813.Largest Sum of Averages/README_EN.md | 244 ++++++++++++++--- .../0813.Largest Sum of Averages/Solution.cpp | 29 ++- .../0813.Largest Sum of Averages/Solution.go | 26 +- .../Solution.java | 9 +- .../0813.Largest Sum of Averages/Solution.py | 9 +- .../0813.Largest Sum of Averages/Solution.ts | 24 ++ .../Solution2.cpp | 22 ++ .../0813.Largest Sum of Averages/Solution2.go | 20 ++ .../Solution2.java | 19 ++ .../0813.Largest Sum of Averages/Solution2.py | 11 + .../0813.Largest Sum of Averages/Solution2.ts | 17 ++ 12 files changed, 572 insertions(+), 104 deletions(-) create mode 100644 solution/0800-0899/0813.Largest Sum of Averages/Solution.ts create mode 100644 solution/0800-0899/0813.Largest Sum of Averages/Solution2.cpp create mode 100644 solution/0800-0899/0813.Largest Sum of Averages/Solution2.go create mode 100644 solution/0800-0899/0813.Largest Sum of Averages/Solution2.java create mode 100644 solution/0800-0899/0813.Largest Sum of Averages/Solution2.py create mode 100644 solution/0800-0899/0813.Largest Sum of Averages/Solution2.ts diff --git a/solution/0800-0899/0813.Largest Sum of Averages/README.md b/solution/0800-0899/0813.Largest Sum of Averages/README.md index 1bf2aa20f8983..3fac54601208e 100644 --- a/solution/0800-0899/0813.Largest Sum of Averages/README.md +++ b/solution/0800-0899/0813.Largest Sum of Averages/README.md @@ -31,9 +31,9 @@ tags:
 输入: nums = [9,1,2,3,9], k = 3
 输出: 20.00000
-解释: 
-nums 的最优分组是[9], [1, 2, 3], [9]. 得到的分数是 9 + (1 + 2 + 3) / 3 + 9 = 20. 
-我们也可以把 nums 分成[9, 1], [2], [3, 9]. 
+解释:
+nums 的最优分组是[9], [1, 2, 3], [9]. 得到的分数是 9 + (1 + 2 + 3) / 3 + 9 = 20.
+我们也可以把 nums 分成[9, 1], [2], [3, 9].
 这样的分组得到的分数为 5 + 2 + 6 = 13, 但不是最大值.
 
@@ -64,17 +64,17 @@ nums 的最优分组是[9], [1, 2, 3], [9]. 得到的分数是 9 + (1 + 2 + 3) / 我们可以先预处理得到前缀和数组 $s$,方便快速得到子数组的和。 -然后设计一个函数 $dfs(i, k)$,表示从数组下标 $i$ 开始,最多分成 $k$ 组的最大平均值和。答案为 $dfs(0, k)$。函数 $dfs(i, k)$ 的执行逻辑如下: +接下来,我们设计一个函数 $\textit{dfs}(i, k)$,表示从数组下标 $i$ 开始,最多分成 $k$ 组的最大平均值和。答案为 $\textit{dfs}(0, k)$。 -当 $i=n$ 时,表示已经遍历到数组末尾,此时返回 $0$。 +函数 $\textit{dfs}(i, k)$ 的执行逻辑如下: -当 $k=1$ 时,表示只剩下一组,此时返回从下标 $i$ 开始到数组末尾的平均值。 +当 $i = n$ 时,表示已经遍历到数组末尾,此时返回 $0$。 -否则,我们在 $[i, ..n-1]$ 的范围内枚举分组的结束位置 $j$,计算从下标 $i$ 到下标 $j$ 的平均值,以及从下标 $j+1$ 开始,最多分成 $k-1$ 组的最大平均值和。取其中的最大值作为答案。 +当 $k = 1$ 时,表示只剩下一组,此时返回从下标 $i$ 开始到数组末尾的平均值。 -为了避免重复计算,我们可以用数组 $f$ 记忆化函数 $dfs(i, k)$ 的返回值。 +否则,我们在 $[i + 1, n)$ 的区间内枚举下一个分组的开始位置 $j$,计算从 $i$ 到 $j - 1$ 的平均值 $\frac{s[j] - s[i]}{j - i}$,加上 $\textit{dfs}(j, k - 1)$ 的结果,取所有结果的最大值。 -时间复杂度 $O(n^2 \times k)$,空间复杂度 $O(n \times k)$。其中 $n$ 表示数组 `nums` 的长度。 +时间复杂度 $O(n^2 \times k)$,空间复杂度 $O(n \times k)$。其中 $n$ 表示数组 $\textit{nums}$ 的长度。 @@ -84,15 +84,14 @@ nums 的最优分组是[9], [1, 2, 3], [9]. 得到的分数是 9 + (1 + 2 + 3) / class Solution: def largestSumOfAverages(self, nums: List[int], k: int) -> float: @cache - def dfs(i, k): + def dfs(i: int, k: int) -> float: if i == n: return 0 if k == 1: - return (s[-1] - s[i]) / (n - i) + return (s[n] - s[i]) / (n - i) ans = 0 - for j in range(i, n): - t = (s[j + 1] - s[i]) / (j - i + 1) + dfs(j + 1, k - 1) - ans = max(ans, t) + for j in range(i + 1, n): + ans = max(ans, (s[j] - s[i]) / (j - i) + dfs(j, k - 1)) return ans n = len(nums) @@ -111,7 +110,7 @@ class Solution { public double largestSumOfAverages(int[] nums, int k) { n = nums.length; s = new int[n + 1]; - f = new Double[n + 1][k + 1]; + f = new Double[n][k + 1]; for (int i = 0; i < n; ++i) { s[i + 1] = s[i] + nums[i]; } @@ -129,9 +128,8 @@ class Solution { return f[i][k]; } double ans = 0; - for (int j = i; j < n; ++j) { - double t = (s[j + 1] - s[i]) * 1.0 / (j - i + 1) + dfs(j + 1, k - 1); - ans = Math.max(ans, t); + for (int j = i + 1; j < n; ++j) { + ans = Math.max(ans, (s[j] - s[i]) * 1.0 /(j - i) + dfs(j, k - 1)); } return f[i][k] = ans; } @@ -147,21 +145,28 @@ public: int n = nums.size(); int s[n + 1]; double f[n][k + 1]; + memset(f, 0, sizeof(f)); s[0] = 0; - memset(f, 0, sizeof f); - for (int i = 0; i < n; ++i) s[i + 1] = s[i] + nums[i]; - function dfs = [&](int i, int k) -> double { - if (i == n) return 0; - if (k == 1) return (s[n] - s[i]) * 1.0 / (n - i); - if (f[i][k]) return f[i][k]; + for (int i = 0; i < n; ++i) { + s[i + 1] = s[i] + nums[i]; + } + auto dfs = [&](auto&& dfs, int i, int k) -> double { + if (i == n) { + return 0; + } + if (k == 1) { + return (s[n] - s[i]) * 1.0 / (n - i); + } + if (f[i][k] > 0) { + return f[i][k]; + } double ans = 0; - for (int j = i; j < n; ++j) { - double t = (s[j + 1] - s[i]) * 1.0 / (j - i + 1) + dfs(j + 1, k - 1); - ans = max(ans, t); + for (int j = i + 1; j < n; ++j) { + ans = max(ans, (s[j] - s[i]) * 1.0 / (j - i) + dfs(dfs, j, k - 1)); } return f[i][k] = ans; }; - return dfs(0, k); + return dfs(dfs, 0, k); } }; ``` @@ -172,25 +177,27 @@ public: func largestSumOfAverages(nums []int, k int) float64 { n := len(nums) s := make([]int, n+1) - f := [110][110]float64{} - for i, v := range nums { - s[i+1] = s[i] + v + for i, x := range nums { + s[i+1] = s[i] + x } - var dfs func(i, k int) float64 + f := make([][]float64, n) + for i := range f { + f[i] = make([]float64, k+1) + } + var dfs func(int, int) float64 dfs = func(i, k int) float64 { if i == n { return 0 } - if k == 1 { - return float64(s[n]-s[i]) / float64(n-i) - } if f[i][k] > 0 { return f[i][k] } - var ans float64 - for j := i; j < n; j++ { - t := float64(s[j+1]-s[i])/float64(j-i+1) + dfs(j+1, k-1) - ans = math.Max(ans, t) + if k == 1 { + return float64(s[n]-s[i]) / float64(n-i) + } + ans := 0.0 + for j := i + 1; j < n; j++ { + ans = math.Max(ans, float64(s[j]-s[i])/float64(j-i)+dfs(j, k-1)) } f[i][k] = ans return ans @@ -199,6 +206,167 @@ func largestSumOfAverages(nums []int, k int) float64 { } ``` +#### TypeScript + +```ts +function largestSumOfAverages(nums: number[], k: number): number { + const n = nums.length; + const s: number[] = Array(n + 1).fill(0); + for (let i = 0; i < n; i++) { + s[i + 1] = s[i] + nums[i]; + } + const f: number[][] = Array.from({ length: n }, () => Array(k + 1).fill(0)); + const dfs = (i: number, k: number): number => { + if (i === n) { + return 0; + } + if (f[i][k] > 0) { + return f[i][k]; + } + if (k === 1) { + return (s[n] - s[i]) / (n - i); + } + for (let j = i + 1; j < n; j++) { + f[i][k] = Math.max(f[i][k], dfs(j, k - 1) + (s[j] - s[i]) / (j - i)); + } + return f[i][k]; + }; + return dfs(0, k); +} +``` + + + + + + + +### 方法二:动态规划 + +我们可以将方法一的记忆化搜索转化为动态规划。 + +定义 $f[i][j]$ 表示数组 $\textit{nums}$ 的前 $i$ 个元素最多分成 $j$ 组的最大平均值和。答案为 $f[n][k]$。 + +对于 $f[i][j]$,我们可以枚举上一组的结束位置 $h$,计算 $f[h][j-1]$,加上 $\frac{s[i]-s[h]}{i-h}$ 的结果,取所有结果的最大值。 + +时间复杂度 $O(n^2 \times k)$,空间复杂度 $O(n \times k)$。其中 $n$ 表示数组 $\textit{nums}$ 的长度。 + + + +#### Python3 + +```python +class Solution: + def largestSumOfAverages(self, nums: List[int], k: int) -> float: + n = len(nums) + f = [[0] * (k + 1) for _ in range(n + 1)] + s = list(accumulate(nums, initial=0)) + for i in range(1, n + 1): + f[i][1] = s[i] / i + for j in range(2, min(i + 1, k + 1)): + for h in range(i): + f[i][j] = max(f[i][j], f[h][j - 1] + (s[i] - s[h]) / (i - h)) + return f[n][k] +``` + +#### Java + +```java +class Solution { + public double largestSumOfAverages(int[] nums, int k) { + int n = nums.length; + double[][] f = new double[n + 1][k + 1]; + int[] s = new int[n + 1]; + for (int i = 0; i < n; ++i) { + s[i + 1] = s[i] + nums[i]; + } + for (int i = 1; i <= n; ++i) { + f[i][1] = s[i] * 1.0 / i; + for (int j = 2; j <= Math.min(i, k); ++j) { + for (int h = 0; h < i; ++h) { + f[i][j] = Math.max(f[i][j], f[h][j - 1] + (s[i] - s[h]) * 1.0 / (i - h)); + } + } + } + return f[n][k]; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + double largestSumOfAverages(vector& nums, int k) { + int n = nums.size(); + int s[n + 1]; + s[0] = 0; + double f[n + 1][k + 1]; + memset(f, 0, sizeof(f)); + for (int i = 0; i < n; ++i) { + s[i + 1] = s[i] + nums[i]; + } + for (int i = 1; i <= n; ++i) { + f[i][1] = s[i] * 1.0 / i; + for (int j = 2; j <= min(i, k); ++j) { + for (int h = 0; h < i; ++h) { + f[i][j] = max(f[i][j], f[h][j - 1] + (s[i] - s[h]) * 1.0 / (i - h)); + } + } + } + return f[n][k]; + } +}; +``` + +#### Go + +```go +func largestSumOfAverages(nums []int, k int) float64 { + n := len(nums) + s := make([]int, n+1) + for i, x := range nums { + s[i+1] = s[i] + x + } + f := make([][]float64, n+1) + for i := range f { + f[i] = make([]float64, k+1) + } + for i := 1; i <= n; i++ { + f[i][1] = float64(s[i]) / float64(i) + for j := 2; j <= min(i, k); j++ { + for h := 0; h < i; h++ { + f[i][j] = max(f[i][j], f[h][j-1]+float64(s[i]-s[h])/float64(i-h)) + } + } + } + return f[n][k] +} +``` + +#### TypeScript + +```ts +function largestSumOfAverages(nums: number[], k: number): number { + const n = nums.length; + const s: number[] = Array(n + 1).fill(0); + for (let i = 0; i < n; i++) { + s[i + 1] = s[i] + nums[i]; + } + const f: number[][] = Array.from({ length: n + 1 }, () => Array(k + 1).fill(0)); + for (let i = 1; i <= n; ++i) { + f[i][1] = s[i] / i; + for (let j = 2; j <= Math.min(i, k); ++j) { + for (let h = 0; h < i; ++h) { + f[i][j] = Math.max(f[i][j], f[h][j - 1] + (s[i] - s[h]) / (i - h)); + } + } + } + return f[n][k]; +} +``` + diff --git a/solution/0800-0899/0813.Largest Sum of Averages/README_EN.md b/solution/0800-0899/0813.Largest Sum of Averages/README_EN.md index 6621ed69ee8fd..80fdbed7ec7b9 100644 --- a/solution/0800-0899/0813.Largest Sum of Averages/README_EN.md +++ b/solution/0800-0899/0813.Largest Sum of Averages/README_EN.md @@ -30,7 +30,7 @@ tags:
 Input: nums = [9,1,2,3,9], k = 3
 Output: 20.00000
-Explanation: 
+Explanation:
 The best choice is to partition nums into [9], [1, 2, 3], [9]. The answer is 9 + (1 + 2 + 3) / 3 + 9 = 20.
 We could have also partitioned nums into [9, 1], [2], [3, 9], for example.
 That partition would lead to a score of 5 + 2 + 6 = 13, which is worse.
@@ -58,7 +58,19 @@ That partition would lead to a score of 5 + 2 + 6 = 13, which is worse.
 
 
 
-### Solution 1
+### Solution 1: Prefix Sum + Memoized Search
+
+We can preprocess to obtain the prefix sum array $s$, which allows us to quickly get the sum of subarrays.
+
+Next, we design a function $\textit{dfs}(i, k)$, which represents the maximum sum of averages when dividing the array starting from index $i$ into at most $k$ groups. The answer is $\textit{dfs}(0, k)$.
+
+The execution logic of the function $\textit{dfs}(i, k)$ is as follows:
+
+-   When $i = n$, it means we have traversed to the end of the array, and we return $0$.
+-   When $k = 1$, it means there is only one group left, and we return the average value from index $i$ to the end of the array.
+-   Otherwise, we enumerate the starting position $j$ of the next group in the interval $[i + 1, n)$, calculate the average value from $i$ to $j - 1$ as $\frac{s[j] - s[i]}{j - i}$, add the result of $\textit{dfs}(j, k - 1)$, and take the maximum value of all results.
+
+The time complexity is $O(n^2 \times k)$, and the space complexity is $O(n \times k)$. Here, $n$ represents the length of the array $\textit{nums}$.
 
 
 
@@ -68,15 +80,14 @@ That partition would lead to a score of 5 + 2 + 6 = 13, which is worse.
 class Solution:
     def largestSumOfAverages(self, nums: List[int], k: int) -> float:
         @cache
-        def dfs(i, k):
+        def dfs(i: int, k: int) -> float:
             if i == n:
                 return 0
             if k == 1:
-                return (s[-1] - s[i]) / (n - i)
+                return (s[n] - s[i]) / (n - i)
             ans = 0
-            for j in range(i, n):
-                t = (s[j + 1] - s[i]) / (j - i + 1) + dfs(j + 1, k - 1)
-                ans = max(ans, t)
+            for j in range(i + 1, n):
+                ans = max(ans, (s[j] - s[i]) / (j - i) + dfs(j, k - 1))
             return ans
 
         n = len(nums)
@@ -95,7 +106,7 @@ class Solution {
     public double largestSumOfAverages(int[] nums, int k) {
         n = nums.length;
         s = new int[n + 1];
-        f = new Double[n + 1][k + 1];
+        f = new Double[n][k + 1];
         for (int i = 0; i < n; ++i) {
             s[i + 1] = s[i] + nums[i];
         }
@@ -113,9 +124,8 @@ class Solution {
             return f[i][k];
         }
         double ans = 0;
-        for (int j = i; j < n; ++j) {
-            double t = (s[j + 1] - s[i]) * 1.0 / (j - i + 1) + dfs(j + 1, k - 1);
-            ans = Math.max(ans, t);
+        for (int j = i + 1; j < n; ++j) {
+            ans = Math.max(ans, (s[j] - s[i]) * 1.0 /(j - i) + dfs(j, k - 1));
         }
         return f[i][k] = ans;
     }
@@ -131,21 +141,28 @@ public:
         int n = nums.size();
         int s[n + 1];
         double f[n][k + 1];
+        memset(f, 0, sizeof(f));
         s[0] = 0;
-        memset(f, 0, sizeof f);
-        for (int i = 0; i < n; ++i) s[i + 1] = s[i] + nums[i];
-        function dfs = [&](int i, int k) -> double {
-            if (i == n) return 0;
-            if (k == 1) return (s[n] - s[i]) * 1.0 / (n - i);
-            if (f[i][k]) return f[i][k];
+        for (int i = 0; i < n; ++i) {
+            s[i + 1] = s[i] + nums[i];
+        }
+        auto dfs = [&](auto&& dfs, int i, int k) -> double {
+            if (i == n) {
+                return 0;
+            }
+            if (k == 1) {
+                return (s[n] - s[i]) * 1.0 / (n - i);
+            }
+            if (f[i][k] > 0) {
+                return f[i][k];
+            }
             double ans = 0;
-            for (int j = i; j < n; ++j) {
-                double t = (s[j + 1] - s[i]) * 1.0 / (j - i + 1) + dfs(j + 1, k - 1);
-                ans = max(ans, t);
+            for (int j = i + 1; j < n; ++j) {
+                ans = max(ans, (s[j] - s[i]) * 1.0 / (j - i) + dfs(dfs, j, k - 1));
             }
             return f[i][k] = ans;
         };
-        return dfs(0, k);
+        return dfs(dfs, 0, k);
     }
 };
 ```
@@ -156,25 +173,27 @@ public:
 func largestSumOfAverages(nums []int, k int) float64 {
 	n := len(nums)
 	s := make([]int, n+1)
-	f := [110][110]float64{}
-	for i, v := range nums {
-		s[i+1] = s[i] + v
+	for i, x := range nums {
+		s[i+1] = s[i] + x
+	}
+	f := make([][]float64, n)
+	for i := range f {
+		f[i] = make([]float64, k+1)
 	}
-	var dfs func(i, k int) float64
+	var dfs func(int, int) float64
 	dfs = func(i, k int) float64 {
 		if i == n {
 			return 0
 		}
-		if k == 1 {
-			return float64(s[n]-s[i]) / float64(n-i)
-		}
 		if f[i][k] > 0 {
 			return f[i][k]
 		}
-		var ans float64
-		for j := i; j < n; j++ {
-			t := float64(s[j+1]-s[i])/float64(j-i+1) + dfs(j+1, k-1)
-			ans = math.Max(ans, t)
+		if k == 1 {
+			return float64(s[n]-s[i]) / float64(n-i)
+		}
+		ans := 0.0
+		for j := i + 1; j < n; j++ {
+			ans = math.Max(ans, float64(s[j]-s[i])/float64(j-i)+dfs(j, k-1))
 		}
 		f[i][k] = ans
 		return ans
@@ -183,6 +202,167 @@ func largestSumOfAverages(nums []int, k int) float64 {
 }
 ```
 
+#### TypeScript
+
+```ts
+function largestSumOfAverages(nums: number[], k: number): number {
+    const n = nums.length;
+    const s: number[] = Array(n + 1).fill(0);
+    for (let i = 0; i < n; i++) {
+        s[i + 1] = s[i] + nums[i];
+    }
+    const f: number[][] = Array.from({ length: n }, () => Array(k + 1).fill(0));
+    const dfs = (i: number, k: number): number => {
+        if (i === n) {
+            return 0;
+        }
+        if (f[i][k] > 0) {
+            return f[i][k];
+        }
+        if (k === 1) {
+            return (s[n] - s[i]) / (n - i);
+        }
+        for (let j = i + 1; j < n; j++) {
+            f[i][k] = Math.max(f[i][k], dfs(j, k - 1) + (s[j] - s[i]) / (j - i));
+        }
+        return f[i][k];
+    };
+    return dfs(0, k);
+}
+```
+
+
+
+
+
+
+
+### Solution 2: Dynamic Programming
+
+We can transform the memoized search from Solution 1 into dynamic programming.
+
+Define $f[i][j]$ to represent the maximum sum of averages when dividing the first $i$ elements of the array $\textit{nums}$ into at most $j$ groups. The answer is $f[n][k]$.
+
+For $f[i][j]$, we can enumerate the end position $h$ of the previous group, calculate $f[h][j-1]$, add the result of $\frac{s[i] - s[h]}{i - h}$, and take the maximum value of all results.
+
+The time complexity is $O(n^2 \times k)$, and the space complexity is $O(n \times k)$. Here, $n$ represents the length of the array $\textit{nums}$.
+
+
+
+#### Python3
+
+```python
+class Solution:
+    def largestSumOfAverages(self, nums: List[int], k: int) -> float:
+        n = len(nums)
+        f = [[0] * (k + 1) for _ in range(n + 1)]
+        s = list(accumulate(nums, initial=0))
+        for i in range(1, n + 1):
+            f[i][1] = s[i] / i
+            for j in range(2, min(i + 1, k + 1)):
+                for h in range(i):
+                    f[i][j] = max(f[i][j], f[h][j - 1] + (s[i] - s[h]) / (i - h))
+        return f[n][k]
+```
+
+#### Java
+
+```java
+class Solution {
+    public double largestSumOfAverages(int[] nums, int k) {
+        int n = nums.length;
+        double[][] f = new double[n + 1][k + 1];
+        int[] s = new int[n + 1];
+        for (int i = 0; i < n; ++i) {
+            s[i + 1] = s[i] + nums[i];
+        }
+        for (int i = 1; i <= n; ++i) {
+            f[i][1] = s[i] * 1.0 / i;
+            for (int j = 2; j <= Math.min(i, k); ++j) {
+                for (int h = 0; h < i; ++h) {
+                    f[i][j] = Math.max(f[i][j], f[h][j - 1] + (s[i] - s[h]) * 1.0 / (i - h));
+                }
+            }
+        }
+        return f[n][k];
+    }
+}
+```
+
+#### C++
+
+```cpp
+class Solution {
+public:
+    double largestSumOfAverages(vector& nums, int k) {
+        int n = nums.size();
+        int s[n + 1];
+        s[0] = 0;
+        double f[n + 1][k + 1];
+        memset(f, 0, sizeof(f));
+        for (int i = 0; i < n; ++i) {
+            s[i + 1] = s[i] + nums[i];
+        }
+        for (int i = 1; i <= n; ++i) {
+            f[i][1] = s[i] * 1.0 / i;
+            for (int j = 2; j <= min(i, k); ++j) {
+                for (int h = 0; h < i; ++h) {
+                    f[i][j] = max(f[i][j], f[h][j - 1] + (s[i] - s[h]) * 1.0 / (i - h));
+                }
+            }
+        }
+        return f[n][k];
+    }
+};
+```
+
+#### Go
+
+```go
+func largestSumOfAverages(nums []int, k int) float64 {
+	n := len(nums)
+	s := make([]int, n+1)
+	for i, x := range nums {
+		s[i+1] = s[i] + x
+	}
+	f := make([][]float64, n+1)
+	for i := range f {
+		f[i] = make([]float64, k+1)
+	}
+	for i := 1; i <= n; i++ {
+		f[i][1] = float64(s[i]) / float64(i)
+		for j := 2; j <= min(i, k); j++ {
+			for h := 0; h < i; h++ {
+				f[i][j] = max(f[i][j], f[h][j-1]+float64(s[i]-s[h])/float64(i-h))
+			}
+		}
+	}
+	return f[n][k]
+}
+```
+
+#### TypeScript
+
+```ts
+function largestSumOfAverages(nums: number[], k: number): number {
+    const n = nums.length;
+    const s: number[] = Array(n + 1).fill(0);
+    for (let i = 0; i < n; i++) {
+        s[i + 1] = s[i] + nums[i];
+    }
+    const f: number[][] = Array.from({ length: n + 1 }, () => Array(k + 1).fill(0));
+    for (let i = 1; i <= n; ++i) {
+        f[i][1] = s[i] / i;
+        for (let j = 2; j <= Math.min(i, k); ++j) {
+            for (let h = 0; h < i; ++h) {
+                f[i][j] = Math.max(f[i][j], f[h][j - 1] + (s[i] - s[h]) / (i - h));
+            }
+        }
+    }
+    return f[n][k];
+}
+```
+
 
 
 
diff --git a/solution/0800-0899/0813.Largest Sum of Averages/Solution.cpp b/solution/0800-0899/0813.Largest Sum of Averages/Solution.cpp
index c790ce7f33a75..77d5123dbd614 100644
--- a/solution/0800-0899/0813.Largest Sum of Averages/Solution.cpp	
+++ b/solution/0800-0899/0813.Largest Sum of Averages/Solution.cpp	
@@ -4,20 +4,27 @@ class Solution {
         int n = nums.size();
         int s[n + 1];
         double f[n][k + 1];
+        memset(f, 0, sizeof(f));
         s[0] = 0;
-        memset(f, 0, sizeof f);
-        for (int i = 0; i < n; ++i) s[i + 1] = s[i] + nums[i];
-        function dfs = [&](int i, int k) -> double {
-            if (i == n) return 0;
-            if (k == 1) return (s[n] - s[i]) * 1.0 / (n - i);
-            if (f[i][k]) return f[i][k];
+        for (int i = 0; i < n; ++i) {
+            s[i + 1] = s[i] + nums[i];
+        }
+        auto dfs = [&](auto&& dfs, int i, int k) -> double {
+            if (i == n) {
+                return 0;
+            }
+            if (k == 1) {
+                return (s[n] - s[i]) * 1.0 / (n - i);
+            }
+            if (f[i][k] > 0) {
+                return f[i][k];
+            }
             double ans = 0;
-            for (int j = i; j < n; ++j) {
-                double t = (s[j + 1] - s[i]) * 1.0 / (j - i + 1) + dfs(j + 1, k - 1);
-                ans = max(ans, t);
+            for (int j = i + 1; j < n; ++j) {
+                ans = max(ans, (s[j] - s[i]) * 1.0 / (j - i) + dfs(dfs, j, k - 1));
             }
             return f[i][k] = ans;
         };
-        return dfs(0, k);
+        return dfs(dfs, 0, k);
     }
-};
\ No newline at end of file
+};
diff --git a/solution/0800-0899/0813.Largest Sum of Averages/Solution.go b/solution/0800-0899/0813.Largest Sum of Averages/Solution.go
index 52f7f8ff4d659..e6d5d0eebe973 100644
--- a/solution/0800-0899/0813.Largest Sum of Averages/Solution.go	
+++ b/solution/0800-0899/0813.Largest Sum of Averages/Solution.go	
@@ -1,28 +1,30 @@
 func largestSumOfAverages(nums []int, k int) float64 {
 	n := len(nums)
 	s := make([]int, n+1)
-	f := [110][110]float64{}
-	for i, v := range nums {
-		s[i+1] = s[i] + v
+	for i, x := range nums {
+		s[i+1] = s[i] + x
 	}
-	var dfs func(i, k int) float64
+	f := make([][]float64, n)
+	for i := range f {
+		f[i] = make([]float64, k+1)
+	}
+	var dfs func(int, int) float64
 	dfs = func(i, k int) float64 {
 		if i == n {
 			return 0
 		}
-		if k == 1 {
-			return float64(s[n]-s[i]) / float64(n-i)
-		}
 		if f[i][k] > 0 {
 			return f[i][k]
 		}
-		var ans float64
-		for j := i; j < n; j++ {
-			t := float64(s[j+1]-s[i])/float64(j-i+1) + dfs(j+1, k-1)
-			ans = math.Max(ans, t)
+		if k == 1 {
+			return float64(s[n]-s[i]) / float64(n-i)
+		}
+		ans := 0.0
+		for j := i + 1; j < n; j++ {
+			ans = math.Max(ans, float64(s[j]-s[i])/float64(j-i)+dfs(j, k-1))
 		}
 		f[i][k] = ans
 		return ans
 	}
 	return dfs(0, k)
-}
\ No newline at end of file
+}
diff --git a/solution/0800-0899/0813.Largest Sum of Averages/Solution.java b/solution/0800-0899/0813.Largest Sum of Averages/Solution.java
index 4599ee5a74209..7b8e6f0e688d1 100644
--- a/solution/0800-0899/0813.Largest Sum of Averages/Solution.java	
+++ b/solution/0800-0899/0813.Largest Sum of Averages/Solution.java	
@@ -6,7 +6,7 @@ class Solution {
     public double largestSumOfAverages(int[] nums, int k) {
         n = nums.length;
         s = new int[n + 1];
-        f = new Double[n + 1][k + 1];
+        f = new Double[n][k + 1];
         for (int i = 0; i < n; ++i) {
             s[i + 1] = s[i] + nums[i];
         }
@@ -24,10 +24,9 @@ private double dfs(int i, int k) {
             return f[i][k];
         }
         double ans = 0;
-        for (int j = i; j < n; ++j) {
-            double t = (s[j + 1] - s[i]) * 1.0 / (j - i + 1) + dfs(j + 1, k - 1);
-            ans = Math.max(ans, t);
+        for (int j = i + 1; j < n; ++j) {
+            ans = Math.max(ans, (s[j] - s[i]) * 1.0 / (j - i) + dfs(j, k - 1));
         }
         return f[i][k] = ans;
     }
-}
\ No newline at end of file
+}
diff --git a/solution/0800-0899/0813.Largest Sum of Averages/Solution.py b/solution/0800-0899/0813.Largest Sum of Averages/Solution.py
index 5f255b46bb0d5..a27a4452c21ae 100644
--- a/solution/0800-0899/0813.Largest Sum of Averages/Solution.py	
+++ b/solution/0800-0899/0813.Largest Sum of Averages/Solution.py	
@@ -1,15 +1,14 @@
 class Solution:
     def largestSumOfAverages(self, nums: List[int], k: int) -> float:
         @cache
-        def dfs(i, k):
+        def dfs(i: int, k: int) -> float:
             if i == n:
                 return 0
             if k == 1:
-                return (s[-1] - s[i]) / (n - i)
+                return (s[n] - s[i]) / (n - i)
             ans = 0
-            for j in range(i, n):
-                t = (s[j + 1] - s[i]) / (j - i + 1) + dfs(j + 1, k - 1)
-                ans = max(ans, t)
+            for j in range(i + 1, n):
+                ans = max(ans, (s[j] - s[i]) / (j - i) + dfs(j, k - 1))
             return ans
 
         n = len(nums)
diff --git a/solution/0800-0899/0813.Largest Sum of Averages/Solution.ts b/solution/0800-0899/0813.Largest Sum of Averages/Solution.ts
new file mode 100644
index 0000000000000..4cb7a0c182087
--- /dev/null
+++ b/solution/0800-0899/0813.Largest Sum of Averages/Solution.ts	
@@ -0,0 +1,24 @@
+function largestSumOfAverages(nums: number[], k: number): number {
+    const n = nums.length;
+    const s: number[] = Array(n + 1).fill(0);
+    for (let i = 0; i < n; i++) {
+        s[i + 1] = s[i] + nums[i];
+    }
+    const f: number[][] = Array.from({ length: n }, () => Array(k + 1).fill(0));
+    const dfs = (i: number, k: number): number => {
+        if (i === n) {
+            return 0;
+        }
+        if (f[i][k] > 0) {
+            return f[i][k];
+        }
+        if (k === 1) {
+            return (s[n] - s[i]) / (n - i);
+        }
+        for (let j = i + 1; j < n; j++) {
+            f[i][k] = Math.max(f[i][k], dfs(j, k - 1) + (s[j] - s[i]) / (j - i));
+        }
+        return f[i][k];
+    };
+    return dfs(0, k);
+}
diff --git a/solution/0800-0899/0813.Largest Sum of Averages/Solution2.cpp b/solution/0800-0899/0813.Largest Sum of Averages/Solution2.cpp
new file mode 100644
index 0000000000000..b63c0a7992fed
--- /dev/null
+++ b/solution/0800-0899/0813.Largest Sum of Averages/Solution2.cpp	
@@ -0,0 +1,22 @@
+class Solution {
+public:
+    double largestSumOfAverages(vector& nums, int k) {
+        int n = nums.size();
+        int s[n + 1];
+        s[0] = 0;
+        double f[n + 1][k + 1];
+        memset(f, 0, sizeof(f));
+        for (int i = 0; i < n; ++i) {
+            s[i + 1] = s[i] + nums[i];
+        }
+        for (int i = 1; i <= n; ++i) {
+            f[i][1] = s[i] * 1.0 / i;
+            for (int j = 2; j <= min(i, k); ++j) {
+                for (int h = 0; h < i; ++h) {
+                    f[i][j] = max(f[i][j], f[h][j - 1] + (s[i] - s[h]) * 1.0 / (i - h));
+                }
+            }
+        }
+        return f[n][k];
+    }
+};
diff --git a/solution/0800-0899/0813.Largest Sum of Averages/Solution2.go b/solution/0800-0899/0813.Largest Sum of Averages/Solution2.go
new file mode 100644
index 0000000000000..d41dde665aa93
--- /dev/null
+++ b/solution/0800-0899/0813.Largest Sum of Averages/Solution2.go	
@@ -0,0 +1,20 @@
+func largestSumOfAverages(nums []int, k int) float64 {
+	n := len(nums)
+	s := make([]int, n+1)
+	for i, x := range nums {
+		s[i+1] = s[i] + x
+	}
+	f := make([][]float64, n+1)
+	for i := range f {
+		f[i] = make([]float64, k+1)
+	}
+	for i := 1; i <= n; i++ {
+		f[i][1] = float64(s[i]) / float64(i)
+		for j := 2; j <= min(i, k); j++ {
+			for h := 0; h < i; h++ {
+				f[i][j] = max(f[i][j], f[h][j-1]+float64(s[i]-s[h])/float64(i-h))
+			}
+		}
+	}
+	return f[n][k]
+}
diff --git a/solution/0800-0899/0813.Largest Sum of Averages/Solution2.java b/solution/0800-0899/0813.Largest Sum of Averages/Solution2.java
new file mode 100644
index 0000000000000..0baacbd295be9
--- /dev/null
+++ b/solution/0800-0899/0813.Largest Sum of Averages/Solution2.java	
@@ -0,0 +1,19 @@
+class Solution {
+    public double largestSumOfAverages(int[] nums, int k) {
+        int n = nums.length;
+        double[][] f = new double[n + 1][k + 1];
+        int[] s = new int[n + 1];
+        for (int i = 0; i < n; ++i) {
+            s[i + 1] = s[i] + nums[i];
+        }
+        for (int i = 1; i <= n; ++i) {
+            f[i][1] = s[i] * 1.0 / i;
+            for (int j = 2; j <= Math.min(i, k); ++j) {
+                for (int h = 0; h < i; ++h) {
+                    f[i][j] = Math.max(f[i][j], f[h][j - 1] + (s[i] - s[h]) * 1.0 / (i - h));
+                }
+            }
+        }
+        return f[n][k];
+    }
+}
diff --git a/solution/0800-0899/0813.Largest Sum of Averages/Solution2.py b/solution/0800-0899/0813.Largest Sum of Averages/Solution2.py
new file mode 100644
index 0000000000000..0f4681532b11e
--- /dev/null
+++ b/solution/0800-0899/0813.Largest Sum of Averages/Solution2.py	
@@ -0,0 +1,11 @@
+class Solution:
+    def largestSumOfAverages(self, nums: List[int], k: int) -> float:
+        n = len(nums)
+        f = [[0] * (k + 1) for _ in range(n + 1)]
+        s = list(accumulate(nums, initial=0))
+        for i in range(1, n + 1):
+            f[i][1] = s[i] / i
+            for j in range(2, min(i + 1, k + 1)):
+                for h in range(i):
+                    f[i][j] = max(f[i][j], f[h][j - 1] + (s[i] - s[h]) / (i - h))
+        return f[n][k]
diff --git a/solution/0800-0899/0813.Largest Sum of Averages/Solution2.ts b/solution/0800-0899/0813.Largest Sum of Averages/Solution2.ts
new file mode 100644
index 0000000000000..245b54632dac2
--- /dev/null
+++ b/solution/0800-0899/0813.Largest Sum of Averages/Solution2.ts	
@@ -0,0 +1,17 @@
+function largestSumOfAverages(nums: number[], k: number): number {
+    const n = nums.length;
+    const s: number[] = Array(n + 1).fill(0);
+    for (let i = 0; i < n; i++) {
+        s[i + 1] = s[i] + nums[i];
+    }
+    const f: number[][] = Array.from({ length: n + 1 }, () => Array(k + 1).fill(0));
+    for (let i = 1; i <= n; ++i) {
+        f[i][1] = s[i] / i;
+        for (let j = 2; j <= Math.min(i, k); ++j) {
+            for (let h = 0; h < i; ++h) {
+                f[i][j] = Math.max(f[i][j], f[h][j - 1] + (s[i] - s[h]) / (i - h));
+            }
+        }
+    }
+    return f[n][k];
+}

From 5765f61cbc30f9ee3d7f40530c4b67aa70b258a8 Mon Sep 17 00:00:00 2001
From: yanglbme 
Date: Mon, 12 Aug 2024 20:11:39 +0800
Subject: [PATCH 2/2] feat: add solutions

---
 .../0814.Binary Tree Pruning/README.md        | 30 +++++++++++------
 .../0814.Binary Tree Pruning/README_EN.md     | 32 +++++++++++++------
 .../0814.Binary Tree Pruning/Solution.cpp     | 10 ++++--
 .../0814.Binary Tree Pruning/Solution.js      |  6 ++--
 .../0814.Binary Tree Pruning/Solution.py      |  4 +--
 .../0814.Binary Tree Pruning/Solution.ts      |  4 +--
 6 files changed, 57 insertions(+), 29 deletions(-)

diff --git a/solution/0800-0899/0814.Binary Tree Pruning/README.md b/solution/0800-0899/0814.Binary Tree Pruning/README.md
index e305386216d61..b20f50170db9e 100644
--- a/solution/0800-0899/0814.Binary Tree Pruning/README.md	
+++ b/solution/0800-0899/0814.Binary Tree Pruning/README.md	
@@ -64,9 +64,13 @@ tags:
 
 
 
-### 方法一:DFS
+### 方法一:递归
 
-观察叶节点,当叶节点 `val` 为 0 时,便将该节点抹去。回溯,查看其父节点是否成为了新的叶节点,依照此规则自底向上。
+我们首先判断当前节点是否为空,如果为空则直接返回空节点。
+
+否则,我们递归地对左右子树进行剪枝,并将剪枝后的左右子树重新赋值给当前节点的左右子节点。然后判断当前节点的值是否为 0 且左右子节点都为空,如果是则返回空节点,否则返回当前节点。
+
+时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为二叉树的节点个数。
 
 
 
@@ -82,10 +86,10 @@ tags:
 class Solution:
     def pruneTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
         if root is None:
-            return None
+            return root
         root.left = self.pruneTree(root.left)
         root.right = self.pruneTree(root.right)
-        if root.val == 0 and root.left is None and root.right is None:
+        if root.val == 0 and root.left == root.right:
             return None
         return root
 ```
@@ -140,10 +144,14 @@ class Solution {
 class Solution {
 public:
     TreeNode* pruneTree(TreeNode* root) {
-        if (!root) return nullptr;
+        if (!root) {
+            return root;
+        }
         root->left = pruneTree(root->left);
         root->right = pruneTree(root->right);
-        if (!root->val && !root->left && !root->right) return nullptr;
+        if (root->val == 0 && root->left == root->right) {
+            return nullptr;
+        }
         return root;
     }
 };
@@ -191,12 +199,12 @@ func pruneTree(root *TreeNode) *TreeNode {
  */
 
 function pruneTree(root: TreeNode | null): TreeNode | null {
-    if (root == null) {
+    if (!root) {
         return root;
     }
     root.left = pruneTree(root.left);
     root.right = pruneTree(root.right);
-    if (root.val == 0 && root.left == null && root.right == null) {
+    if (root.val === 0 && root.left === root.right) {
         return null;
     }
     return root;
@@ -262,10 +270,12 @@ impl Solution {
  * @return {TreeNode}
  */
 var pruneTree = function (root) {
-    if (!root) return null;
+    if (!root) {
+        return root;
+    }
     root.left = pruneTree(root.left);
     root.right = pruneTree(root.right);
-    if (root.val == 0 && !root.left && !root.right) {
+    if (root.val === 0 && root.left === root.right) {
         return null;
     }
     return root;
diff --git a/solution/0800-0899/0814.Binary Tree Pruning/README_EN.md b/solution/0800-0899/0814.Binary Tree Pruning/README_EN.md
index 39d06266717c3..eb5b39b48e3c7 100644
--- a/solution/0800-0899/0814.Binary Tree Pruning/README_EN.md	
+++ b/solution/0800-0899/0814.Binary Tree Pruning/README_EN.md	
@@ -28,7 +28,7 @@ tags:
 
 Input: root = [1,null,0,0,1]
 Output: [1,null,0,null,1]
-Explanation: 
+Explanation:
 Only the red nodes satisfy the property "every subtree not containing a 1".
 The diagram on the right represents the answer.
 
@@ -61,7 +61,13 @@ The diagram on the right represents the answer. -### Solution 1 +### Solution 1: Recursion + +First, we check if the current node is null. If it is, we directly return the null node. + +Otherwise, we recursively prune the left and right subtrees and reassign the pruned subtrees to the current node's left and right children. Then, we check if the current node's value is 0 and both its left and right children are null. If so, we return the null node; otherwise, we return the current node. + +Time complexity is $O(n)$, and space complexity is $O(n)$. Here, $n$ is the number of nodes in the binary tree. @@ -77,10 +83,10 @@ The diagram on the right represents the answer. class Solution: def pruneTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]: if root is None: - return None + return root root.left = self.pruneTree(root.left) root.right = self.pruneTree(root.right) - if root.val == 0 and root.left is None and root.right is None: + if root.val == 0 and root.left == root.right: return None return root ``` @@ -135,10 +141,14 @@ class Solution { class Solution { public: TreeNode* pruneTree(TreeNode* root) { - if (!root) return nullptr; + if (!root) { + return root; + } root->left = pruneTree(root->left); root->right = pruneTree(root->right); - if (!root->val && !root->left && !root->right) return nullptr; + if (root->val == 0 && root->left == root->right) { + return nullptr; + } return root; } }; @@ -186,12 +196,12 @@ func pruneTree(root *TreeNode) *TreeNode { */ function pruneTree(root: TreeNode | null): TreeNode | null { - if (root == null) { + if (!root) { return root; } root.left = pruneTree(root.left); root.right = pruneTree(root.right); - if (root.val == 0 && root.left == null && root.right == null) { + if (root.val === 0 && root.left === root.right) { return null; } return root; @@ -257,10 +267,12 @@ impl Solution { * @return {TreeNode} */ var pruneTree = function (root) { - if (!root) return null; + if (!root) { + return root; + } root.left = pruneTree(root.left); root.right = pruneTree(root.right); - if (root.val == 0 && !root.left && !root.right) { + if (root.val === 0 && root.left === root.right) { return null; } return root; diff --git a/solution/0800-0899/0814.Binary Tree Pruning/Solution.cpp b/solution/0800-0899/0814.Binary Tree Pruning/Solution.cpp index a9f3cf3538d75..3affab559427e 100644 --- a/solution/0800-0899/0814.Binary Tree Pruning/Solution.cpp +++ b/solution/0800-0899/0814.Binary Tree Pruning/Solution.cpp @@ -12,10 +12,14 @@ class Solution { public: TreeNode* pruneTree(TreeNode* root) { - if (!root) return nullptr; + if (!root) { + return root; + } root->left = pruneTree(root->left); root->right = pruneTree(root->right); - if (!root->val && !root->left && !root->right) return nullptr; + if (root->val == 0 && root->left == root->right) { + return nullptr; + } return root; } -}; \ No newline at end of file +}; diff --git a/solution/0800-0899/0814.Binary Tree Pruning/Solution.js b/solution/0800-0899/0814.Binary Tree Pruning/Solution.js index 402f8916795d7..af8b610f20320 100644 --- a/solution/0800-0899/0814.Binary Tree Pruning/Solution.js +++ b/solution/0800-0899/0814.Binary Tree Pruning/Solution.js @@ -11,10 +11,12 @@ * @return {TreeNode} */ var pruneTree = function (root) { - if (!root) return null; + if (!root) { + return root; + } root.left = pruneTree(root.left); root.right = pruneTree(root.right); - if (root.val == 0 && !root.left && !root.right) { + if (root.val === 0 && root.left === root.right) { return null; } return root; diff --git a/solution/0800-0899/0814.Binary Tree Pruning/Solution.py b/solution/0800-0899/0814.Binary Tree Pruning/Solution.py index 339d237429ba0..68e16641aff50 100644 --- a/solution/0800-0899/0814.Binary Tree Pruning/Solution.py +++ b/solution/0800-0899/0814.Binary Tree Pruning/Solution.py @@ -7,9 +7,9 @@ class Solution: def pruneTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]: if root is None: - return None + return root root.left = self.pruneTree(root.left) root.right = self.pruneTree(root.right) - if root.val == 0 and root.left is None and root.right is None: + if root.val == 0 and root.left == root.right: return None return root diff --git a/solution/0800-0899/0814.Binary Tree Pruning/Solution.ts b/solution/0800-0899/0814.Binary Tree Pruning/Solution.ts index 115665c66a60b..b85a17d0dfe9e 100644 --- a/solution/0800-0899/0814.Binary Tree Pruning/Solution.ts +++ b/solution/0800-0899/0814.Binary Tree Pruning/Solution.ts @@ -13,12 +13,12 @@ */ function pruneTree(root: TreeNode | null): TreeNode | null { - if (root == null) { + if (!root) { return root; } root.left = pruneTree(root.left); root.right = pruneTree(root.right); - if (root.val == 0 && root.left == null && root.right == null) { + if (root.val === 0 && root.left === root.right) { return null; } return root;