解决找数字问题

奇数个的那个数

给定些数字,这些数中只有一个数出现了奇数次,找出这个数。
Input
每组数据第一行n表示数字个数,1 <= n <= 2 ^ 18 且 n % 2 == 1。
接下来n行每行一个32位有符号整数。
Output
出现奇数次那个数,每组数据对应一行。
Sample Input
5
1
1
2
2
3


7
1
2
1
2
2
3

Sample Output
3
2

这里可以用异或(异或_ :http://baike.baidu.com/link?url=rObpv9NerpblUhee9BnU9H837A4yJmYByTxKgUic8dESAl9Bv32F61diLFYFChaIaGJsLw0jMF-m3L6IHXzkeq)来解决。

异或运算的几个性质:

1、A xor A = 0,也就是说异或同一个数偶数次,结果不变。

2、异或运算满足交换律。

这样我们只需要按顺序把所有的数依次异或一遍,剩下的就是唯一出现奇数次的那个数了。

代码:

#include<cstdio>
using namespace std;
int n,ans=0;
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        int x;
        ans=0;
        while(n--)
        {
            scanf("%d",&x);
            ans^=x;
        }
        printf("%d
",ans);
    }
    return 0;
}
还有一个更加复杂的问题,就是有2个数字出现奇数次,当然,这里n就是偶数了,该如何解决呢?

假设这两个数为a,b,将数组中所有元素异或结果x=a^b,判断x中位为1的位数(注:因为a!=b,所以x!=0,我们只需知道某一个位为1的位数k,例如0010 1100,我们可取k=2或者3,或者5),然后将x与数组中第k位为1的数进行异或,异或结果就是a,b中一个,然后用x异或,就可以求出另外一个。
      为什么呢?因为x中第k位为1表示a或b中有一个数的第k位也为1,假设为a,我们将x与数组中第k位为1的数进行异或时,也即将x与a外加其他第k位为1的出现过偶数次的数进行异或,化简即为x与a异或,结果是b。

代码:

#include<cstdio>
using namespace std;
 int a[1000005];
int main()
{
    int n,ans1,ans2,x;
    while(scanf("%d",&n)!=EOF)
    {
        x=0;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            x^=a[i];
        }
        ans1=x;ans2=x;
        int k=0;
        while(!(ans1&1))//注意一定要用括号,因为优先级不一样
        {
            ans1>>=1;
            k++;
        }
        for(int i=0;i<n;i++)
        {
            if((a[i]>>k)&1)
            {
                x^=a[i];
            }
        }
        printf("%d %d
",x,(x^ans2));
    }
    return 0;
}




原文地址:https://www.cnblogs.com/Zeroinger/p/5493928.html