Largest Sum of Averages 最大平均值和的分组

我们将给定的数组 A 分成 K 个相邻的非空子数组 ,我们的分数由每个子数组内的平均值的总和构成。计算我们所能得到的最大分数是多少。

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

示例:
输入: 
A = [9,1,2,3,9]
K = 3
输出: 20
解释: 
A 的最优分组是[9], [1, 2, 3], [9]. 得到的分数是 9 + (1 + 2 + 3) / 3 + 9 = 20.
我们也可以把 A 分成[9, 1], [2], [3, 9].
这样的分组得到的分数为 5 + 2 + 6 = 13, 但不是最大值.

说明:

  • 1 <= A.length <= 100.
  • 1 <= A[i] <= 10000.
  • 1 <= K <= A.length.
  • 答案误差在 10^-6 内被视为是正确的。

思路:采用带记忆数组的递归,维护一个三维数组memo,其中memo[i][j][k]表示从下标i到下标为j需要分成k组的最大平均值是多少。那么这是一个递归的过程,每次把需分成k组分为第一组和剩下的k-1组,那么第一组计算从下标i为left~(right - (K - 1))的子数组平均值和(相当于每次加一个数字,然后除以已加的数字的个数)和递归调用剩下的i+1开始的k-1个子数组的和中取最大,核心代码如下:

double tmp = 0.0;
	int count = 1;
	double res = 0.0;
	for (int i = left; i <= (right - (K - 1)); i++) {
		tmp += A[i];
		res = max(res, tmp / count + largestSumOfAveragesCore(i + 1, right, K - 1, A,memo));
		count++;
	}

然后用一个记忆数组memo[left][right][k]保存计算过得从下标为left到下标为right的子数组中分为k组的最大平均值,最后返回所有memo值中最大的值即可。

参考代码:

class Solution {
public:
double largestSumOfAveragesCore(int left, int right, int K, vector<int>& A, vector<vector<vector<double>>> &memo) {
	if (memo[left][right][K] != -1) {
		return memo[left][right][K];
	}
	if (K == 1) {
		double cur = 0.0;
		for (int i = left; i <= right; i++) {
			cur += A[i];
		}
		memo[left][right][K] = cur / (right - left + 1);
		return memo[left][right][K];
	}
	if ((right - left + 1) < K) {
		return 0.0;
	}
	if ((right - left + 1) == K) {
		double cur = 0.0;
		for (int i = left; i <= right; i++) {
			cur += A[i];
		}
		memo[left][right][K] = cur;
		return memo[left][right][K];
	}
	double tmp = 0.0;
	int count = 1;
	double res = 0.0;
	for (int i = left; i <= (right - (K - 1)); i++) {
		tmp += A[i];
		res = max(res, tmp / count + largestSumOfAveragesCore(i + 1, right, K - 1, A,memo));
		count++;
	}
	memo[left][right][K] = res;
	return memo[left][right][K];
}
double largestSumOfAverages(vector<int>& A, int K) {
	double res = 0.0;
	vector<vector<vector<double>>> memo(A.size(), vector<vector<double>>(A.size(),vector<double>(K+1,-1)));
	res = largestSumOfAveragesCore(0, A.size() - 1, K, A,memo);
	return res;
}
};





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值