最大平均值和的分组
难度:
标签:
题目描述
代码结果
运行时间: 54 ms, 内存: 16.1 MB
/*
* 思路:
* 1. 动态规划的核心思想与普通Java解法相同。
* 2. 主要区别在于使用Java Stream API来处理数组和计算前缀和。
* 3. Stream API可以使代码更简洁,但对于性能提升不明显。
*/
import java.util.stream.IntStream;
public class Solution {
public double largestSumOfAverages(int[] nums, int k) {
int n = nums.length;
double[] prefixSum = new double[n + 1];
IntStream.range(0, n).forEach(i -> prefixSum[i + 1] = prefixSum[i] + nums[i]);
double[][] dp = new double[n + 1][k + 1];
IntStream.rangeClosed(1, n).forEach(i -> dp[i][1] = prefixSum[i] / i);
IntStream.rangeClosed(2, k).forEach(j -> IntStream.rangeClosed(j, n).forEach(i -> IntStream.range(j - 1, i).forEach(m -> dp[i][j] = Math.max(dp[i][j], dp[m][j - 1] + (prefixSum[i] - prefixSum[m]) / (i - m)))));
return dp[n][k];
}
}
解释
方法:
这道题可以使用动态规划来解决。我们定义 f[i][j] 表示将前 i 个数分成 j 组所能得到的最大分数。我们可以枚举最后一组的起始位置 k,将问题转化为求 f[k][j-1] + avg(k+1, i) 的最大值,其中 avg(k+1, i) 表示第 k+1 个数到第 i 个数的平均值。为了避免重复计算前缀和,我们可以预处理前缀和数组 pre。最后的答案即为 f[n][k]。
时间复杂度:
O(n^2*k)
空间复杂度:
O(n)
代码细节讲解
🦆
在动态规划解法中,`f[i][j]`的定义是什么?在代码中似乎使用了一维数组,这是如何实现的?
▷🦆
为什么在动态规划的内层循环中,子数组的结束位置`j`的循环起始于`n-k+i`?这一设计的目的是什么?
▷🦆
在计算平均值`avg(k+1, i)`时,使用前缀和数组`pre`可以避免哪些类型的重复计算?具体是如何通过前缀和优化计算的?
▷🦆
在代码实现中,为什么需要在`i == 1`的情况下单独处理,直接计算前`j`个数的平均值?这与其他情况有何不同?
▷