同一个子数组中出现两个数字(连续)

时间:2017-07-20 04:59:45

标签: c++ arrays algorithm

给定一个整数数组,找到具有相同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

1 个答案:

答案 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_mapO(n)时间(基于地图选择) - 以及O(nlogn)额外空间。

Demo on ideone