给定一个整数数组,找到具有相同x和y数的连续子序列的总数。 例如,对于x = 1且y = 2,数组[1,2,1] ans = 2表示其两个子数组[1,2]和[2,1]。 检查每个连续的子序列是O(n ^ 2),效率太低。有任何改进的想法吗?
这是我写的代码
int get_total(int* a,int x,int y,int n){
int result=0;
for(int i=0;i<n;i++){
int x_c=0,y_c=0;
for(int j=i;j<n;j++){
if(a[j]==x){
x_c++;
}
if(a[j]==y){
y_c++;
}
if(x_c==y_c){
result++;
}
}
}
return result;
}
int main(){
int n,q;
cin >>n >>q;
int a[n];
for(int i=0;i<n;i++){
cin >>a[i];
}
while(q--){
int x,y;
cin >>x >>y;
cout <<get_total(a,x,y,n)<<"\n";
}
}
每次查询都以n ^ 2运行。 最大数组大小为8 * 10 ^ 3,查询最大数量为10 ^ 5
答案 0 :(得分:5)
创建辅助阵列x_y_diffs
,基本上是:
#(times_x_appeared_thus_far) - #(times_y_appeared_thus_far)
可以计算为:
x_y_diffs[0] = 0
x_y_diffs[i] = x_y_diffs[i-1] + 1 if array[i-1] == x
x_y_diffs[i-1] - 1 if array[i-1] == y
x_y_diffs[i-1] otherwise
很容易看出它可以在线性时间内计算出来。
现在,观察一个“好的”子序列(i,j)开始和结束x_y_diffs[i+1] == x_y_diffs[j+1]
。
因此,您可以简单地迭代数组并维护一个直方图,计算每个值出现的次数。
std::map<int, int> histogram;
int count = 0;
for (int x : x_y_diffs) {
count += histogram[x];
histogram[x] = histogram[x] + 1;
}
这需要O(nlogn)
时间来计算(每个地图插入/搜索都是O(logn)
),并且可以通过从{切换到O(n)
平均情况来改进{1}}至std::map
。
因此,算法总计std::unordred_map
或O(n)
时间(基于地图选择) - 以及O(nlogn)
额外空间。