[leetcode] 813. Largest Sum of Averages

441 篇文章 0 订阅
289 篇文章 0 订阅

Description

We partition a row of numbers A into at most K adjacent (non-empty) groups, then our score is the sum of the average of each group. What is the largest score we can achieve?

Note that our partition must use every number in A, and that scores are not necessarily integers.

Example:

Input: 
A = [9,1,2,3,9]
K = 3
Output: 20
Explanation: 
The best choice is to partition A into [9], [1, 2, 3], [9]. The answer is 9 + (1 + 2 + 3) / 3 + 9 = 20.
We could have also partitioned A into [9, 1], [2], [3, 9], for example.
That partition would lead to a score of 5 + 2 + 6 = 13, which is worse.

Note:

  • 1 <= A.length <= 100.
  • 1 <= A[i] <= 10000.
  • 1 <= K <= A.length.
  • Answers within 10^-6 of the correct answer will be accepted as correct.

分析

题目的意思是:把一个数组分成K组,然后计算每组的平均值,求和使得平均值之和最小。

dp[k][i]表示前i+1个元素(0~i)最多分k个组是平均数和最大,然后就是自己手动写一个表可以简单推导一下.表格如下:
k \ i 0 1 2 3 4
0 9.00 5.00 4.00 3.75 4.80
1 9.00 10.00 10.50 11.00 12.75
2 9.00 10.00 12.00 13.50 20.00

  • 自己认认真真打完表后很容易就可以推导dp的方程:
    dp[k][i] = max(dp[k - 1][i], dp[k - 1][j] + (sum[j + 1, i] / (i - j)); (k > = 1, sum[j + 1, i]表示区间j+1到i中间所有数的和)
  • 当然求区间和的话我们可以做一下预处理保证sum[j+1,i]是O(1)时间就可以.

代码

class Solution {
public:
    double largestSumOfAverages(vector<int>& A, int K) {
        int n=A.size();
        vector<double> sum(n+1,0);
        for(int i=1;i<=n;i++){
            sum[i]=A[i-1]+sum[i-1];
        }
        vector<vector<double>> dp(K,vector<double>(n,0));
        for(int k=0;k<K;k++){
            for(int i=0;i<n;i++){
                dp[k][i]=k==0 ? sum[i+1]/(i+1):dp[k-1][i];
                if(k>0){
                   for(int j=i-1;j>=0;j--){
                    dp[k][i]=max(dp[k][i],dp[k-1][j]+(sum[i+1]-sum[j+1])/(i-j));
                    } 
                } 
            }
        }
        return dp[K-1][n-1];
    }
};

分析二

设dp[i][k]表示将数组中前i个元素分成k个相邻的非空子数组,可以得到的最大分数。dp[i][k]可以通过dp[i][k-1]推导而来,其中j<i,状态转移方程为:

dp[i][k]=max(dp[i][k],dp[i][k-1]+average(j+1,i))
dp[i][0]=average(0,i)
average(j+1,i)=(A[j+1]+A[j+2]+...+A[i])/(i-j)

average(j+1,i)可以通过累加数组得到。

进一步,假设dp[i][k]为第K层的结果,第K层的结果只与K-1层有关,因此可以使用滚动数组优化空间,即只使用两个一维数组。进一步,如果我们从后往前进行动态规划,即dp[i][k]表示数组A中从第i个元素开始到结尾A[i:]分成k个相邻的非空子数组,可以得到最大分数,状态转移方程将变为:

dp[i][k]=max(dp[i][k],dp[i][k-1]+average(i,j-1))
dp[i][0]=average(i,n-1)

其中j>i,那么在计算第k层结果,并且在i依次递增的时候,第k层的结果不会覆盖掉第k-1层的结果。因此我们最终只需要用一个一维数组,就能完成动态规划。倒过来以后,最终的结果就是dp[0]了。

代码二(python)

class Solution:
    def largestSumOfAverages(self, A: List[int], K: int) -> float:
        n=len(A)
        sums=[0]
        for i in range(n):
            sums.append(sums[-1]+A[i])
        
        dp=[0]*(n+1)
        for i in range(n):
            dp[i]=(sums[n]-sums[i])/(n-i)
        for k in range(K-1):
            for i in range(n):
                for j in range(i+1,n):
                    dp[i]=max(dp[i],dp[j]+(sums[j]-sums[i])/(j-i))
        return dp[0]

参考文献

Leetcode 813. Largest Sum of Averages
solution

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

农民小飞侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值