Keshawn_lu's Blog

Leetcode 813. 最大平均值和的分组

字数统计: 528阅读时长: 2 min
2022/11/28 Share

题目简介:

给定数组 nums 和一个整数 k 。我们将给定的数组 nums 分成 最多 k 个相邻的非空子数组 。 分数 由每个子数组内的平均值的总和构成。

注意我们必须使用 nums 数组中的每一个数进行分组,并且分数不一定需要是整数。

返回我们所能得到的最大 分数 是多少。答案误差在 10-6 内被视为是正确的。

示例 1:

1
2
3
4
5
6
输入: 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].
这样的分组得到的分数为 5 + 2 + 6 = 13, 但不是最大值.

提示:

  • 1 <= nums.length <= 100
  • 1 <= nums[i] <= 10^4
  • 1 <= k <= nums.length

思路:

首先我们将每个元素的前缀和求出来。

定义一个函数solve(n, k),用于计算以下标n开始,分成k组的最大平均值总和。

  • n == dp.size()时,说明已到数组末尾,返回0
  • k == 1时,说明只剩下最后一组,将剩余的元素全部加入这一组即可
  • 否则,从[n, ..., nums.size() - 1]开始遍历可能的情况,获得最大值。

为防止重复运算,加入res数组用于存储已经计算过的结果。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Solution {
public:

double solve(int n, int k, vector<int>& dp, vector<vector<double>>& res){

if(n == dp.size())
return 0; //已到末尾

if(res[n][k])
return res[n][k];

if(k == 1)
return (dp[dp.size() - 1] - dp[n]) * 1.0 / (dp.size() - n - 1);

double ans = 0.0;
for(int i = n + 1; i < dp.size(); i++){

double temp = (dp[i] - dp[n]) * 1.0 / (i - n) + solve(i, k - 1, dp, res);

ans = max(ans, temp);
}

res[n][k] = ans;
return ans;
}

double largestSumOfAverages(vector<int>& nums, int k) {

vector<int> dp(nums.size() + 1);
dp[0] = 0;

for(int i = 0; i < nums.size(); i++)
dp[i + 1] = dp[i] + nums[i];

vector<vector<double>> res(dp.size(), vector<double>(k + 1));
return solve(0, k, dp, res);
}
};
CATALOG
  1. 1. 题目简介:
  2. 2. 思路:
  3. 3. 代码如下: