修改数组(散列表,数组)

问题:

给定一个长度为 N 的数组 A = [A1, A2, · · · AN ],数组中有可能有重复出现 的整数。

现在小明要按以下方法将其修改为没有重复整数的数组。小明会依次修改 A2,A3,··· ,AN。

当修改 Ai 时,小明会检查 Ai 是否在 A1 ∼ Ai−1 中出现过。如果出现过,则 小明会给 Ai 加上 1 ;如果新的 Ai 仍在之前出现过,小明会持续给 Ai 加 1 ,直 到 Ai 没有在 A1 ∼ Ai−1 中出现过。

当 AN 也经过上述修改之后,显然 A 数组中就没有重复的整数了。 现在给定初始的 A 数组,请你计算出最终的 A 数组

输入

第一行包含一个整数 N。 第二行包含N个整数A1,A2,··· ,AN

输出

输出N个整数,依次是最终的A1,A2,··· ,AN。

样例输入

5

2 1 1 3 4

样例输出

2 1 3 4 5

分析:

1,可以采用暴力破解法,双层for循环,第一层,循环n个数,第二次循环i之前的数,碰到相同的,加1,j从0开始,继续判断是否有相同的

    int n;

    cin>>n;

    int p[n];

    for(int i=0;i

        cin>>p[i];

        for(int j=0;j

            if(p[i]==p[j]){

                p[i]++;

                j=-1;

            }

            if(j==i-1){

                break;

            }

        }

        cout<

    }

2,采用散列表法,用一个v数组用来存储每次访问过的数,记为1,没有访问的记为0,这个数组的下标就是你输入的数,对应的,这样可以找到对应的数是否被访问过

比如:

int v[1000099];

    for(int i=0;i<1000099;i++){

        v[i]=0;

    }

    int n;

    cin>>n;

    int *p=new int[n];

    for(int i=0;i

        cin>>p[i];

        while(1){

            if(v[p[i]]==1){//说明被访问过

                p[i]++;

            }else{//没有被访问过的,就赋予1

                v[p[i]]=1;

                break;

            }

        }

        cout<

    }

3,优化上面的散列表法,我们发现,如果把v数组改为存储每个数访问的次数的时候,循环的次数又会变少

如果v[i]=k,说明i这个元素被访问过k次了,后面的k个元素也都被访问过了,只要访问i+k,看v[i+k]是否被访问过,一直到v[i]==0

int v[1000099];//存储每次访问的次数

    for(int i=0;i<1000099;i++){

        v[i]=0;

    }

    int n;

    cin>>n;

    int *p=new int[n];

    for(int i=0;i

        cin>>p[i];

        while(1){

            if(v[p[i]]!=0){//说明被访问过了,p[i]=他自身加上他访问过的次数

                v[p[i]]++;

                p[i]+=v[p[i]]-1;

            }else{//没有被访问过的,就自加1

                v[p[i]]++;

                break;

            }

        }

    }

    for(int i=0;i

        cout<

    }

结果:

你可能感兴趣的:(修改数组(散列表,数组))