from typing import List
class Solution:
def largestSumOfAverages(self, nums: List[int], k: int) -> float:
n = len(nums)
prefix = [0] * (n + 1)
for i in range(n):
prefix[i+1] = prefix[i] + nums[i]
dp = [[0.0] * (k+1) for _ in range(n+1)]
for i in range(1, n+1):
dp[i][1] = prefix[i] / i
for parts in range(2, k+1):
for i in range(parts, n+1):
for j in range(parts-1, i):
dp[i][parts] = max(dp[i][parts], dp[j][parts-1] + (prefix[i] - prefix[j]) / (i - j))
return dp[n][k]
#include <vector>
#include <algorithm>
using namespace std;
class Solution {
public:
double largestSumOfAverages(vector<int>& nums, int k) {
int n = nums.size();
vector<double> prefix(n+1, 0);
for (int i = 0; i < n; ++i)
prefix[i+1] = prefix[i] + nums[i];
vector<vector<double>> dp(n+1, vector<double>(k+1, 0.0));
for (int i = 1; i <= n; ++i)
dp[i][1] = prefix[i] / i;
for (int parts = 2; parts <= k; ++parts) {
for (int i = parts; i <= n; ++i) {
for (int j = parts-1; j < i; ++j) {
dp[i][parts] = max(dp[i][parts], dp[j][parts-1] + (prefix[i] - prefix[j]) / (i - j));
}
}
}
return dp[n][k];
}
};
class Solution {
public double largestSumOfAverages(int[] nums, int k) {
int n = nums.length;
double[] prefix = new double[n+1];
for (int i = 0; i < n; ++i) {
prefix[i+1] = prefix[i] + nums[i];
}
double[][] dp = new double[n+1][k+1];
for (int i = 1; i <= n; ++i) {
dp[i][1] = prefix[i] / i;
}
for (int parts = 2; parts <= k; ++parts) {
for (int i = parts; i <= n; ++i) {
for (int j = parts-1; j < i; ++j) {
dp[i][parts] = Math.max(dp[i][parts], dp[j][parts-1] + (prefix[i] - prefix[j]) / (i - j));
}
}
}
return dp[n][k];
}
}
var largestSumOfAverages = function(nums, k) {
const n = nums.length;
const prefix = new Array(n+1).fill(0);
for (let i = 0; i < n; ++i) {
prefix[i+1] = prefix[i] + nums[i];
}
const dp = Array.from({length: n+1}, () => new Array(k+1).fill(0));
for (let i = 1; i <= n; ++i) {
dp[i][1] = prefix[i] / i;
}
for (let parts = 2; parts <= k; ++parts) {
for (let i = parts; i <= n; ++i) {
for (let j = parts-1; j < i; ++j) {
dp[i][parts] = Math.max(dp[i][parts], dp[j][parts-1] + (prefix[i] - prefix[j]) / (i - j));
}
}
}
return dp[n][k];
};
nums
, into at most k
non-empty, contiguous subarrays. For each subarray, you calculate its average (the sum of its elements divided by its length), and then sum up all these averages. Your goal is to maximize this total sum of averages by choosing the best possible partitioning.
nums
must be included in exactly one subarray.k
partitions if it leads to a higher sum.nums
: A list of positive integers.k
: An integer representing the maximum number of partitions.k
parts, calculating the sum of averages for each partitioning, and picking the maximum. However, this quickly becomes infeasible for larger arrays because the number of possible partitions grows exponentially.
nums[i:j]
as prefix[j] - prefix[i]
.dp[i][k]
where dp[i][k]
represents the largest sum of averages for the first i
elements of nums
using k
partitions.k=1
), the best we can do is the average of the first i
elements: dp[i][1] = prefix[i] / i
.j
(where the last partition starts after j
), and update dp[i][k]
as:dp[i][k] = max(dp[i][k], dp[j][k-1] + average(nums[j:i]))
average(nums[j:i]) = (prefix[i] - prefix[j]) / (i - j)
dp[n][k]
, where n
is the length of nums
.k
are considered, but in a way that avoids redundant calculations.
nums = [9, 1, 2, 3, 9]
and k = 3
:
prefix = [0, 9, 10, 12, 15, 24]
dp[1][1] = 9/1 = 9
dp[2][1] = 10/2 = 5
dp[3][1] = 12/3 = 4
dp[4][1] = 15/4 = 3.75
dp[5][1] = 24/5 = 4.8
dp[5][2]
, try splitting at each possible j
:dp[1][1] + average(1,5) = 9 + (24-9)/(5-1) = 9 + 3.75 = 12.75
dp[2][1] + average(2,5) = 5 + (24-10)/(5-2) = 5 + 4.67 = 9.67
k=3
partitions
dp[5][3]
, try splitting at each possible j
where the previous partition ends.dp[5][3] = 20
n
is the length of nums
and k
is the maximum number of partitions.dp[i][parts]
, we check up to i
split points, so total time is O(n2k).