九度 题目1351:数组中只出现一次的数字

来源:互联网 发布:淘宝买麻古暗语 编辑:程序博客网 时间:2024/05/22 05:17

题目来源:http://ac.jobdu.com/problem.php?pid=1351

时间限制:1 秒

内存限制:32 兆

特殊判题:

提交:1946

解决:563

题目描述:
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
输入:
每个测试案例包括两行:
第一行包含一个整数n,表示数组大小。2<=n <= 10^6。
第二行包含n个整数,表示数组元素,元素均为int。
输出:
对应每个测试案例,输出数组中只出现一次的两个数。输出的数字从小到大的顺序。
样例输入:
82 4 3 6 3 2 5 5
样例输出:
4 6
   这个题很好,题目中说明,只有两个数只出现一次,其余的只出现两次,那么又知道相同的两个数异或为0,现在就是把数组分成两个部分,每一部分中只有一个数出现一次。

怎么分?首先tmp = 0,tmp与数组中每个数都异或,得到一个值,其二进制,找到从最右边起第1次出现1的位置,标记为iPos。按iPos位置是不是1来分,一部分该位置全是1,另一部分该位置全部为零(我们知道iPos为1,那么两个只出现一次的数,在该位置肯定有一个为零,另一个不为零)。由此可得解!


#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int MAXN = 1000010;int IsBit1(int num, unsigned int index){    num = (num >> index);    return (num & 1);}unsigned int FindFirstBitIs1 (int num){    int indexBit = 0;    while ((num & 1) == 0 && indexBit < 32)    {        num >>= 1;        ++indexBit;    }    return indexBit;}void FindNumAppearOnce(int* arr, int n, int &n1, int &n2){    if(arr == NULL || n < 2)        return ;    int i, iFirstOne;    unsigned int tmp = 0;    for(i = 0; i < n; ++i)        tmp ^= arr[i];    iFirstOne = FindFirstBitIs1(tmp);    for(i = 0; i < n; ++i)    {        if(IsBit1(arr[i], iFirstOne))            n1 ^= arr[i];        else            n2 ^= arr[i];    }}int main(){    int n, i;    int arr[MAXN];    while(scanf("%d", &n) != EOF)    {        int num1 = 0;        int num2 = 0;        for(i = 0; i < n; ++i)            scanf("%d", &arr[i]);        FindNumAppearOnce(arr, n, num1, num2);        if(num1 > num2)            num1 ^= num2, num2 ^= num1, num1 ^= num2;        printf("%d %d\n", num1, num2);    }    return 0;}


0 0
原创粉丝点击