您的位置:首页 > 其它

(算法)和为0的最大连续子数组

2015-09-26 10:58 381 查看

题目:

和为零的最大连续子数组

思路:

我首先想到的是前缀数组和,遍历一遍数组,计算出sum[i](表示从0-i的子数组之和)。

有了前缀数组和,只要sum[i]=sum[j](i<j),那么区间[i+1,j]就是和为零的子数组,只要在遍历前缀数组和时记录最长的区间即可。

需要注意的是:当sum[i]等于0时,其区间为[0,i]。

在判断sum[i]=sum[j](i<j)时,有个查找的过程,要么直接遍历j左边的所有数(增加时间复杂度),要么通过map来存储对应和的下标位置(空间换时间)。(详见代码)

代码:

#include<iostream>
#include<vector>
#include<map>

using namespace std;

// O(n^2)
int longestSubArrayOfSumZero_1(const vector<int> &arr){
int sz=arr.size();
vector<int> preSum(sz+1,0);

for(int i=0;i<sz;i++){
preSum[i+1]=preSum[i]+arr[i];
}

int longest=0;
int start=0;
for(int i=1;i<=sz;i++){
for(int j=0;j<i;j++){
if(preSum[i]==preSum[j] && (i-j)>longest){
longest=i-j;
start=j;
}
}
}

for(int i=start;i<start+longest;i++)
cout<<arr[i]<<" ";
cout<<endl;

return longest;
}

// O(n)
int longestSubArrayOfSumZero_2(const vector<int> &arr){
int sz=arr.size();
int longest=0;
map<int,int> pos;
int sum=0;
pos[sum]=0;
int start=0;

for(int i=0;i<sz;i++){
sum+=arr[i];
if(pos.find(sum)!=pos.end()){
int len=i-pos[sum];
if(len>longest){
longest=len;
start=pos[sum]+1;
}
}
else
pos[sum]=i;

}

for(int i=start;i<start+longest;i++)
cout<<arr[i]<<" ";
cout<<endl;
return longest;
}

int main(){
int n;
while(cin>>n){
vector<int> arr(n);
for(int i=0;i<n;i++){
cin>>arr[i];
}

cout<< longestSubArrayOfSumZero_1(arr) <<endl;
cout<< longestSubArrayOfSumZero_2(arr) <<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: