题目:
We partition a row of numbers A into at most K adjacent
(non-empty) groups, then our score is the sum of the average of each group. What is the largest score we can achieve?
Note that our partition must use every number in A, and that scores are not necessarily integers.
Example: Input: A = [9,1,2,3,9] K = 3 Output: 20 Explanation: The best choice is to partition A into [9], [1, 2, 3], [9]. The answer is 9 + (1 + 2 + 3) / 3 + 9 = 20. We could have also partitioned A into [9, 1], [2], [3, 9], for example. That partition would lead to a score of 5 + 2 + 6 = 13, which is worse.
Note:
1 <= A.length <= 100.1 <= A[i] <= 10000.1 <= K <= A.length.- Answers within
10^-6of the correct answer will be accepted as correct.
思路:
我感觉这道题目应该是一道中等难度的动态规划问题。首先明确一点,就是把组划分的越多,则平均数之和越大,所以只要K不超过A中的元素个数,那么的结果一定是对应划分成了K组,而不是比K小的组。
我们定义dp[i][k]表示将A[0]到A[i]这i+1个元素划分成为k组的话,平均数之和的最大值,然后推导递推公式:
1)如果k == 1,说明我们将这i+1个元素归为1组,所以dp[i][k] = avg(A[0],...A[i]);
2)如果k > 1,那么我么可以采用的策略是:将A[j], A[i]这i-j+1个数划分为1组,那么此时就需要将A[0],...A[j - 1]划分成为另外的k-1组(k - 1 <= j <= i)。在这所有的划分方法中,我们需要取使得dp[i][k]达到最大值的那种划分,所以dp[i][k] = max(dp[j - 1][k - 1] + avg(A[j],...A[i])), k - 1 <= j <= i。最后得到的dp[n - 1][K]即为所求。
由于我们需要求不同区间的平均数,所以在程序的第一步,我们首先利用O(n)的时间复杂度计算出A数组的累积和,这样在后面就可以在O(1)时间内求出任意区间内数值的平均值了。
算法的时间复杂度是O(kn^2),空间复杂度是O(kn),但是注意到dp[i][k]之和dp[j][k - 1]有关,其中k - 1 <= j <= i。所以实际上我们还可以进一步优化,将空间复杂度降低到O(n),这一步就留给读者了^_^。
代码:
class Solution {
public:
double largestSumOfAverages(vector<int>& A, int K) {
// step 1: calculate the accumulated sums of A
int n = A.size();
vector<int> sums(n, 0);
sums[0] = A[0];
for (int i = 1; i < n; ++i) {
sums[i] = sums[i - 1] + A[i];
}
// step 2: calculate the largest sum of averages using DP
// dp[i][k] means the largest sum of averages in A[0, i] after partitioning in k groups
vector<vector<double>> dp(n, vector<double>(K + 1, 0.0));
for (int k = 1; k <= K; ++k) {
for (int i = 0; i < n; ++i) {
if (k == 1) { // treat all the elements in one group
dp[i][k] = sums[i] / static_cast<double>(i + 1);
}
else if (k > i + 1) { // less than k elements, so impossible
continue;
}
else { // 1 < k <= i + 1
for (int j = k - 1; j <= i; ++j) { // try to group A[j], ...A[i] together
double part1 = dp[j - 1][k - 1];
double part2 = (sums[i] - sums[j - 1]) / static_cast<double>(i - j + 1);
if (dp[i][k] < part1 + part2) {
dp[i][k] = part1 + part2;
}
}
}
}
}
return dp[n - 1][K];
}
};
LeetCode 813:动态规划求最大平均数之和
这篇博客介绍了LeetCode 813题的解题思路,通过动态规划方法求解将数组分成K组时的最大平均数之和。博主认为这是一道中等难度的动态规划问题,提出了初始状态与状态转移方程,并指出可以通过预计算累积和优化求解过程,将空间复杂度降低到O(n)。最后,博主给出了算法的时间复杂度和空间复杂度。
209

被折叠的 条评论
为什么被折叠?



