[杨小白]_leetcode_力扣_11月28日每日一题_813. 最大平均值和的分组

109 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情

前言

小白算法比较菜,希望能激励我每日更新,从leetcode第一题开始,2022年目标1900分,现在1806!!

11月28日每日一题

813. 最大平均值和的分组

给定数组 nums 和一个整数 k 。我们将给定的数组 nums 分成 最多 k 个相邻的非空子数组 。 分数 由每个子数组内的平均值的总和构成。

注意我们必须使用 nums 数组中的每一个数进行分组,并且分数不一定需要是整数。

返回我们所能得到的最大 分数 是多少。答案误差在 10-6 内被视为是正确的。

示例 1:

输入: nums = [9,1,2,3,9], k = 3

输出: 20.00000

解释:

nums 的最优分组是[9], [1, 2, 3], [9]. 得到的分数是 9 + (1 + 2 + 3) / 3 + 9 = 20.

我们也可以把 nums 分成[9, 1], [2], [3, 9].

这样的分组得到的分数为 5 + 2 + 6 = 13, 但不是最大值.

示例 2:

  • 输入: nums = [1,2,3,4,5,6,7], k = 4
  • 输出: 20.50000

提示:

  • 1 <= nums.length <= 100
  • 1 <= nums[i] <= 104
  • 1 <= k <= nums.length

代码

长度100,本以为可以用递归搜索,结果好像不太行,代码如代码一,下面这个示例过不去,但是如果面试手撕的时候,可以两个方法都试试,应该会是加分项。

image.png [4663,3020,7789,1627,9668,1356,4207,1133,8765,4649,205,6455,8864,3554,3916,5925,3995,4540,3487,5444,8259,8802,6777,7306,989,4958,2921,8155,4922,2469,6923,776,9777,1796,708,786,3158,7369,8715,2136,2510,3739,6411,7996,6211,8282,4805,236,1489,7698] 27 解法一(递归)

class Solution {
    double max = 0;

    public double largestSumOfAverages(int[] nums, int k) {
        max = 0;
        dfs(nums, k, 0, 0, 0);
        return max;
    }

    //index 是组 have是序号
    private void dfs(int[] nums, int k, int index, int have, double res) {
        if (have == nums.length) {
            if (index == k) {
                max = Math.max(max, res);
            }
            return;
        }
        if (index > k) {
            return;
        }
        double temp = 0;
        for (int i = have; i < nums.length; i++) {
            temp = temp + nums[i];
            dfs(nums, k, index + 1, i + 1, res + temp / (i - have + 1));
        }
    }
}

解法二(dp)

dp[i][k] 表示将前i个数,分为k组

dp[i][j] 如果的更新是由dp[a][j - 1] a从0到i-1,加上a到i分为一组的平均值

  • dp[i][j] = Math.max(dp[i][j], dp[l][j - 1] + (preSum[i+1] - preSum[l+1]) / (i - l));

经典dp做法。

class Solution {
    public double largestSumOfAverages(int[] nums, int k) {
        double[][] dp = new double[nums.length][k + 1];
        double[] preSum = new double[nums.length + 1];
        for (int i = 0; i < nums.length; i++) {
            preSum[i + 1] = preSum[i] + nums[i]; //presum[i] = num[0] +++num[i - 1]
            dp[i][1] = preSum[i + 1] / (i + 1);
        }
        for (int i = 1; i < nums.length; i++) {
            for (int j = 2; j <= k; j++) {
                for (int l = 0; l < i; l++) {
                    dp[i][j] = Math.max(dp[i][j], dp[l][j - 1] + (preSum[i+1] - preSum[l+1]) / (i - l));
                }
            }
        }
        return dp[nums.length - 1][k];
    }
}