前缀和

  例:求一个数组的和为0的连续最长子串

  arr[]数组存放原数组,sum[]为前缀和数组,用map存储前缀和每一个数字第一次出现的下标。比如现在前缀和为10,所以要查找前缀和为-10第一次出现的位置,找道后就是前缀和为10的和为0的最长的子段。

  代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <vector>
 4 #include <map>
 5 
 6 using namespace std;
 7 
 8 // O(n^2)
 9 int longestSubArrayOfSumZero_1(const vector<int> &arr){
10     int sz=arr.size();
11     vector<int> preSum(sz+1,0);
12 
13     for(int i=0;i<sz;i++){
14         preSum[i+1]=preSum[i]+arr[i];
15     }
16 
17     int longest=0;
18     int start=0;
19     for(int i=1;i<=sz;i++){
20         for(int j=0;j<i;j++){
21             if(preSum[i]==preSum[j] && (i-j)>longest){
22                 longest=i-j;
23                 start=j;
24             }
25         }
26     }
27     for(int i=start;i<start+longest;i++)
28         printf("%d",arr[i]);
29     printf("\n");
30     return longest;
31 }
32 
33 
34 // O(n)
35 int longestSubArrayOfSumZero_2(const vector<int> &arr){
36     int sz=arr.size();
37     int longest=0;
38     map<int,int> pos;
39     int sum=0;
40     pos[sum]=0;
41     int start=0;
42 
43     for(int i=0;i<sz;i++){
44         sum+=arr[i];
45         if(pos.find(sum)!=pos.end()){
46             int len=i-pos[sum]+1;
47             if(len>longest){
48                 longest=len;
49                 start=pos[sum];
50             }
51         }
52         else
53             pos[sum]=i;
54 
55     }
56     for(int i=start;i<start+longest;i++)
57         printf("%d",arr[i]);
58     printf("\n");
59     return longest;
60 }
61 
62 int main(){
63     int n;
64     while(~scanf("%d",&n)){
65         vector<int> arr(n);
66         for(int i=0;i<n;i++){
67             scanf("%d",&arr[i]);
68         }
69         printf("%d\n",longestSubArrayOfSumZero_1(arr));
70         printf("%d\n",longestSubArrayOfSumZero_2(arr));
71     }
72     return 0;
73 }

 

转载于:https://www.cnblogs.com/wz-archer/p/10163029.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值