最大平均(和)子序列
来源:互联网 发布:mc9s12xs128单片机实验 编辑:程序博客网 时间:2024/06/16 05:46
描述
给定n个数的数组,找到所有长度大于等于k的连续子数组中平均值最大的那个。返回那个最大的平均值。
1 <= k <= n <= 10000,数组中的元素在范围[-10000, 10000]之间,最后返回的答案的误差应在10^(-5)以内。
样例
输入:[1,12,-5,-6,50,3], k = 4
输出:12.75
说明
长度为4的子数组中,最大的平均值为12.75,(=(12 + -5 + -6 + 50)/4)
长度为5的子数组中,最大的平均值为10.8,(=(12 + -5 + -6 + 50 + 3)/5)
长度为6的子数组中,最大的平均值为9.16667。(所有数的平均值)
因此返回12.75。
分析
首先,考虑把求平均问题转换为求和问题,实质上是一样的,然后用二分枚举,求出最大和。关键在于转换和二分,二分法此类题通用。求长度大于等于k的最大和子数组比原问题容易的多,令s为b的前缀和子数组,即s(i)=b(0)+b(1)+……+b(i-1),且s(0)=0,那么b(j)到b(i-1)的区间和可表示为s(i)-s(j)。
找长度大于等于k的最大和子数组等价于找i,j,满足i-j>=k,且使s(i)-s(j)最大。固定i,则要使s(i)-s(j)最大,s(j)应最小,同时也应满足j<=i-k,令p(i) = min{s(j)},j<=i-k,故 i 固定时s(i)-s(j)的最大值为s(i)-p(i),枚举所有i即可得到最终的最大值。
二分的初始区间可以设置为[min{a(i)},i=0~n-1 , max{a(i)},i=0~n-1],因为一组数的平均值不会小于这组数的最小值,也不会大于这组数的最大值。对于二分值A,通过前面讲的方法以O(n)的时间判断是否有子数组的平均值大于等于A,若有则答案大于等于A,若没有,则答案小于A。二分至区间长度小于所需精度,即可返回该值。
测试
#include<bits/stdc++.h>using namespace std;class Solution{public: double find(const int n,int *num,int k){ double left=INT_MAX, right=INT_MIN; for(int i=0;i<n;i++){ left=left<(double)num[i]?left:(double)num[i]; right=right>(double)num[i]?right:(double)num[i]; } double sum[n+1]; while(right-left>1e-6){ double mid=(left+right)/2; for(int i=0;i<n;i++){ sum[i+1]=sum[i]+num[i]-mid; } double preMin=0; double sumMax=INT_MIN; for(int i=k;i<=n;i++){ sumMax=sumMax>sum[i]-preMin?sumMax:(sum[i]-preMin); preMin=preMin<sum[i-k+1]?preMin:sum[i-k+1]; } if(sumMax>=0){ left=mid; } else{ right=mid; } } return left; }};int main(){ Solution sol; int k,n; cin>>n>>k; int a[10001]; for(int i=0;i<n;i++){ cin>>a[i]; } double result=sol.find(n,a,k); cout<<result<<endl; return 0;}
若需继续使用斜率优化,可以参考:
http://blog.csdn.net/lxc779760807/article/details/51366552
- 最大平均(和)子序列
- 最大子序列和
- 最大子序列和
- 最大和子序列
- 最大子序列和
- 最大子序列和
- 最大子序列和
- 最大子序列和
- 最大子序列和?
- 最大子序列和
- 最大子序列和
- 和最大子序列
- 最大子序列和
- 最大子序列和
- 最大子序列和
- 最大子序列和
- 最大子序列和
- 最大和子序列
- 浅谈this关键字的三种常用用法:
- Go接口
- String类的intern()方法详解
- inf安装驱动方式---win10下使用VS2015+WDK10生成win7 X64的设备驱动的过程
- Java学习
- 最大平均(和)子序列
- SQL Server的安全模型
- CAB归档文件提取工具cabextract
- 深入理解javascript原型和闭包(15)——闭包
- 数塔问题
- android ui素材
- 系统学习Java高并发
- Xcode操作流
- 课堂练习4: 编写代码模拟手机与SIM卡的组合关系。 要求: SIM卡类负责创建SIM卡; Phone类负责创建手机; 手机可以组合一个