• 找出2n+1个数中不成对的那个


    在网上看到一篇相关的文章,感叹算法的巧妙。

    用O(n)复杂度搞定。

    异或操作(^)——(对于操作)相同为0,相异为1.比如:1^0 = 1, 1 ^1=0

    这样:

    • 两个相同的数异或就为0
    • 任何数和0异或为自己(转化到位。1^0 = 1, 0 ^0=0

    对于2,1,3,2,1, (2^2)^(1^1)^3=3.如此就能将不成对的3找出来。

    异或具有交换律,所以可以按顺序计算,2^1^3^2^1=3。

    代码如下:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int a[7] = {1, 2, 1, 2, 3, 5, 5};
    
    int main(){
        int i, ans = 0;
    
        for(i=0; i<7; i++){
            ans ^= a[i];
        }
    
        printf("%d\n", ans);
        return 0;
    }

    问题升级版:

    (1)给出n个数,其中有且仅有一个出现了奇数次,其余的都出现了偶数次。用线性时间常数空间找出这个出现奇数次的数

    (2)给定n个数,其中有且仅有两个出现了奇数次,其余的都出现了偶数次。用线性时间常数空间找出这两个出现奇数次的数

    对于问题1,就不解释了。

    对于问题2,

    1.对所有的数异或一遍,得到的数肯定不为0,

    2.在二进制中从右向左找第一个值为1的位置,也就是说这两个出现奇数次的数的二进制在此位置的值肯定不同,按照在这个位置的不同值(即0或1)将所有数分成两组,分别异或运算,所得的结果就是这两个出现奇数次的数。

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int a[6] = {4, 3, 1, 56, 3, 1};
    
    int main(){
        int i, ans1, ans2, k, pos;
        k=0;
        for(i=0; i<6; i++) k ^= a[i];
    
        for(pos=1; (k&pos) == 0; pos<<=1);
    
        ans1 = ans2 = 0;
    
        for(i=0; i<6; i++){
            if((a[i]&pos) == 0) ans2 ^= a[i];
            else ans1 ^= a[i];
        }
    
        printf("%d %d\n", ans1, ans2);
    
        return 0;
    }

    原文地址1:http://www.cnblogs.com/kaituorensheng/archive/2013/04/03/2998829.html

    原文地址2:http://www.cnblogs.com/kaituorensheng/archive/2013/04/04/3000033.html

  • 相关阅读:
    luogu 1593
    luogu 1369
    hdu 1796
    bzoj 3398
    luogu 4587
    luogu 2152
    bzoj 3629
    bzoj 1507: [NOI2003]Editor
    bzoj 1503: [NOI2004]郁闷的出纳员
    bzoj 1497: [NOI2006]最大获利
  • 原文地址:https://www.cnblogs.com/tanhehe/p/3000658.html
Copyright © 2020-2023  润新知