(算法)和为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; }
相关文章推荐
- 树的深度优先与广度优先遍历
- 用硕鼠下载土豆视频
- 条款41:了解隐式接口和编译期多态
- 线段树查询
- 野人学Android基础篇之网络通讯第二课--本地apache服务器与Android的连接
- cmd命令 从C盘转到D盘
- 滴滴出行2015在线笔试题目
- C++ string类型的split字符串分割函数
- HDOJ1495 非常可乐(bfs)
- 懒人造就了方法
- MySql创建本地用户和远程用户 并赋予权限
- PAT(甲级)1057
- asp+jsp+JavaScript动态实现添加数据行
- java 抽象类和接口
- log4j配置
- 大道至简第二章读后感
- C++ Primer Plus第六版 第十一章 编程练习答案
- 【软件工程作业01】
- PAT(甲级)1056
- CF#317-C. Lengthening Sticks-组合数学