大家晚上,直截了当地问。
我们得到一个整数数组。我们必须报告k1 th,k2 th和k3 最大子阵列总和。阵列大小(最多10 ^ 6)。元素都是+ ve 和-ve。 K1,K2,K3< = 2200;
换句话说,我们必须找到S [K]的值,其中to 数组S包含所有可能的连续子数组的总和 递减顺序。
线性解可能是O(n)还是O(nlogn)?
我的方法是这样的(不正确)
我内心深处知道这可以通过对数组进行排序并使用两种指针技术来解决。我可以找到所有可能的子数组和。在排序中间数之后,我们可以解决但是我无法正确实现它。
任何人都有其他方法或相同的方法但是正确吗?
如果你想看到我对问题的实现
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define nline cout<<"\n"
#define fast ios_base::sync_with_stdio(false)cin.tie(0)
#define ain(A, B, C) assert(IN(A, B, C))
#define ull unsigned long long int
#define ll long long int
#define pii pair<int,int>
#define MAXX 100009
#define fr(a,b,i) for(int i=a;i<b;i++)
vector<int>G[MAXX];
bool vis[MAXX];
int n,k1,k2,k3;
bool cmp(const int &l,const int &r){
return l>r;
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>k1>>k2>>k3;
--k1,--k2,--k3;
int a[n+1];
for(int i=0;i<n;i++)cin>>a[i];
sort(a,a+n);
int l=0,e=n-1;
vector<ll>v;
int sum=0;
while(e>=l)
{
if(a[e]>a[l])
{
sum+=a[e];
v.pb(sum);
e--;
}
else
{
sum+=a[l];
v.pb(sum);
l++;
}
}
sort(v.begin(),v.end(),cmp);
cout<<v[k1]<<" "<<v[k2]<<" "<<v[k3]<<endl;
}
return 0;
}
答案 0 :(得分:1)
根据wikipedia,您应该能够使用Kadane算法在O(n)中找到1个子阵列,所以我的猜测是找到最大子阵列,存储它,然后将其删除并再次搜索对于第二个最大子阵列等...
我假设您使用了一个跟踪子阵列索引的Kadane算法版本。
伪代码
init_array(array) //here you initialize your array with the number you want in it
start1,end1,sum1 = kadane(array) // you find the starting index, the ending index and the maximal sum of the subarray
remove(array, start1,end1) // here you remove the subarray in array.
如果你这样做3次,你有3个最大子阵列,你可以将它们相加。
我看到的唯一限制是,你需要删除O(n)或更少的子阵列,以保持算法在O(n)。 (而不是删除它,你可以跟踪你可以访问或不访问的索引,可能会更快)