leetcode
leetcode 701 ~ 750
最大平均值和的分组

最大平均值和的分组

难度:

标签:

题目描述

代码结果

运行时间: 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]`的定义是什么?在代码中似乎使用了一维数组,这是如何实现的?
`f[i][j]` 在动态规划中的定义是将前 `i` 个数分成 `j` 组所能得到的最大分数。在代码中使用了一维数组 `f`,而非二维数组,是因为在计算过程中,每个状态 `f[j]` 只依赖于当前行的前一个状态(`f[l]`)和上一个分组数的状态。因此,可以通过从后向前更新 `f[j]` 来保证在更新 `f[j]` 时使用的是上一分组的数据,从而节省空间复杂度,将原本的二维数组压缩为一维数组。
🦆
为什么在动态规划的内层循环中,子数组的结束位置`j`的循环起始于`n-k+i`?这一设计的目的是什么?
在内层循环中,`j` 的循环起始于 `n-k+i` 是为了确保每个分组中至少有一个元素。由于总共有 `n` 个元素分成 `k` 组,最少每组一个元素,因此第 `i` 组的结束位置 `j` 至少需要保留足够的元素给剩余的 `k-i` 组。这样设计可以有效地减少不必要的循环迭代,避免计算那些不可能的状态,提高代码的运行效率。
🦆
在计算平均值`avg(k+1, i)`时,使用前缀和数组`pre`可以避免哪些类型的重复计算?具体是如何通过前缀和优化计算的?
在计算子数组的平均值时,如果不使用前缀和数组,则每次计算都需要遍历子数组来求和,这在多次计算时会导致大量的重复计算。通过使用前缀和数组 `pre`,可以快速计算任意子数组的和,即 `pre[j] - pre[i-1]` 表示从第 `i` 到第 `j` 的元素和。这样,计算平均值可以直接用 `(pre[j] - pre[i-1]) / (j - i + 1)` 实现,大大降低了时间复杂度。
🦆
在代码实现中,为什么需要在`i == 1`的情况下单独处理,直接计算前`j`个数的平均值?这与其他情况有何不同?
当 `i == 1` 时,意味着只分成一组,这种情况下,整个数组本身就是一组,因此直接计算从第 1 个元素到第 `j` 个元素的总平均值即可,无需进行分组或使用更复杂的动态规划转移。这是基础情况,为后续分更多组做准备。在 `i > 1` 的情况下,需要考虑将数组分成多组,需要使用动态规划来寻找最优分组方案。

相关问题