最大平均值和的分组 | 动态规划
题目大意:
将给定的数组 nums 分成 k 个相邻的非空子数组,使得由每个子数组内的平均值的总和最大化。
数据范围:
1 <= nums.length <= 100
1 <= nums[i] <= 10^4
1 <= k <= nums.length
思路分析:
直接枚举每种划分方案,最坏情况下共有C(100, 50)种组合,无法暴力计算。
拆分子问题,可以发现如果先解决将子数组划分为 k-1 段的最大平均和,合并剩余部分为一段,则原问题答案为所有子问题解中的最优解。
从自顶向下的角度来看,结论是显然的:将给定的数组 nums 分成 k 个相邻的非空子数组,必然存在某个间断点 s 使得 [s, n-1]为一段,而 average(nums[s:n]) + subproblem(nums[: s], k-1) 是最大的。
因而问题转化为求解新的子问题:将给定的数组 nums[: s] 分成 k-1 个相邻的非空子数组,使得由每个子数组内的平均值的总和最大化。
实际可以采用自下而上的合并方式求解。
AC代码:
class Solution:
def largestSumOfAverages(self, nums: List[int], k: int) -> float:
n = len(nums)
# dp[i][j] nums[:i] 划分j段 平均和
dp = [[0]*(k+1) for _ in range(n)]
for i in range(n):
dp[i][1] = sum(nums[:i+1]) / (i+1)
for i in range(n):
for j in range(2, min(i+1, k)+1): # 注意上下界
for s in range(i):
dp[i][j] = max(dp[i][j], dp[s][j-1]+sum(nums[s+1:i+1])/(i-s)) # [s+1:i+1]区间内总和可以预处理
return dp[n-1][k]
(完)