About the topic:
Given an integer array of length n and an integer k, you need to find the number of consecutive subarrays in the array that sum to k,
Test sample:
enter:
5 3
1 1 2 1 1
output:
2
Idea 1:
Use the for loop to violently enumerate the sub-arrays, and sum + count, the time complexity is O(n^3). (If the data is greater than 100, this idea is definitely Time Limit Exceeded (time overtime), so it needs to be optimized)!
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,k; //定义
scanf("%d%d",&n,&k); //输入
int a[n],sum=0; //定义数组和计数器
for(int i=0;i<n;i++) //for循环输入
scanf("%d",a[i]); //输入下标为i的数
for(int i=0;i<n;i++){ //区间i枚举
for(int j=0;j<n;j++){ //区间j枚举
int ans=0; //区间和计数数组
for(int x=i;x<=j;x++) //求出区间[i,j]的和
ans+=a[i]; //计数
if(ans==k) //比较
sum++; //计数
}
}
cout<<sum<<endl; //输出
return 0;
}
Idea 2:
We can also use the prefix sum to solve this problem. First, preprocess the prefix array sum of a, calculate the sum of the sub-arrays each time, and then perform the double-loop interval enumeration, and then compare it with k. The time complexity is O (n^2). (If the data is not greater than 1500, it can be AC, and there is still room for optimization).
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,k; //定义
scanf("%d%d",&n,&k); //输入
int sum[n+1]={0},ans=0; //定义前缀和数组sum和计数器ans
sum[0]=0; //将下标为0的地址初始化为0
for(int i=1;i<=n;i++){ //进行循环n次读入
int a; //定义
scanf("%d",&a); //输入
sum[i]=sum[i-1]+a; //求前缀和
}
for(int i=1;i<=n;i++) //区间枚举i
for(int j=0;j<n;j++) //区间枚举j
if(sum[i]-sum[j]==k) //求出区间[i,j]的和与k比较
ans++; //计数器加1
cout<<ans<<endl; //输出计数器
return 0; //结束
}
Idea 3:
We can use map (a class defined by the STL library), prefix and optimize. In the idea of using the prefix sum alone, we require whether the sum of a subarray with the subscript i at the end is k, we need to traverse j from 0 to i-1 to find whether there is sum[i]-k= sum[j]. Then we only use map to save the prefix sum of the first i elements, save the value of the prefix sum before the number of occurrences (>i), and finally judge whether the map contains sum[i]-k.
The time complexity is O(n), which is already very fast, and the data can be AC if it is as large as several million.
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,k; //定义
scanf("%d%d",&n,&k); //输入
int sum[n+1]={0},ans=0; //定义前缀和数组sum和计数器ans
sum[0]=0; //将下标为0的地址初始化为0
map<int,int> p; //定义map
for(int i=1;i<=n;i++){ //进行循环n次读入
int a; //定义
scanf("%d",&a); //输入
sum[i]=sum[i-1]+a; //求前缀和
p[sum[i]]++; //进行存储
}
for(int i=0;i<n;i++) //进行区间判断
ans+=p[sum[i]+k]; //计数
cout<<ans<<endl; //输出
return 0; //结束
}
Summarize:
This question is a very classic question in prefix sums, which is equivalent to a stepping stone, and there are more difficult differences, two-dimensional prefix sums, etc...