作者:小迅
链接:https://leetcode.cn/problems/largest-sum-of-averages/solutions/1995361/dong-tai-gui-hua-zhu-shi-chao-ji-xiang-x-x9wc/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
题目
思路
平均值和最大的分组的子数组数目必定是 k --> 因为数组元素大于 1 那么任意一个子数组的平均值肯定 >= 1,那么累加肯定会增大
为了方便计算子数组的平均值,我们使用一个数组 sum 来保存数组 nums 的前缀和。其中 dp[i][j] 的含义 表示 nums 在区间 [0,i−1] 被切分成 j 个子数组的最大平均值和,显然 i≥j,计算分两种情况讨论:
当 j=1 时,dp[i][j] 是对应区间 [0, i - 1] 的平均值;
当 j>1 时,我们可以将区间 [0, i - 1] 分成 [0, x - 1] 和 [x, i - 1] 两个部分,其中 x≥j−1,并且不唯一
那么 dp[i][j] 等于所有这些合法的切分方式的平均值和的最大值。即转移表达式为 :dp[i][j] = MAX(dp[i][j], dp[x][j - 1] + (sum[i] - sum[x]) / (i - x)),其中 dp[x][j - 1] + (sum[i] - sum[x]) / (i - x) 表示为 x 位置 之前的最大值分组和 + 当前位置平均值
代码
#define MAX(a, b) ((a) > (b) ? (a) :(b))
double largestSumOfAverages(int* nums, int numsSize, int k){
double sum[numsSize + 1];
sum[0] = 0.0;
for (int i = 0; i < numsSize; ++i) {//前缀和
sum[i+1] = sum[i] + nums[i];
}
double dp[numsSize + 1][k + 1];
for (int i = 1; i <= numsSize; ++i) {//最佳分组
dp[i][1] = sum[i] / i;
}
for (int j = 2; j <= k; ++j) {//枚举分组数
for (int i = j; i <= numsSize; ++i) {//枚举数组元素
dp[i][j] = 0.0;
for (int x = j - 1; x < i; ++x) {//枚举分割位置
dp[i][j] = MAX(dp[i][j], dp[x][j - 1] + (sum[i] - sum[x]) / (i - x));//取最佳分组位置和
}
}
}
return dp[numsSize][k];
}
作者:小迅
链接:https://leetcode.cn/problems/largest-sum-of-averages/solutions/1995361/dong-tai-gui-hua-zhu-shi-chao-ji-xiang-x-x9wc/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。