找出出现偶数次中两个奇数频率的数,空间O(1)

本题时间O(n),空间O(1);

Problem Description
有一行n个数,其中所有数都恰好出现了两次,除了两个特殊的数只出现了一次。现在Quasrain想知道这两个特殊的数分别是多少

Input 多组数据。

第一行一个整数T表示数据组数(T<=5)

对于每组数据,第一行一个整数n,意义如题面所示(保证n为偶数,n<=1000000)

接下来一行n个正整数Ai。(0<=Ai<2^31-1)

Output 对于每组数据,输出一行两个正整数,表示两个特殊的数,请按从小到大的顺序输出

Sample Input 2

4

2 2 3 4

6

1 2 3 2 3 5

Sample Output
3 4
1 5

Hint
建议使用高效的读入方式

不允许用数组存储这n个整数

其实这一题是下面这道题的加强版

1到N这N个数字中,何老板将其中一个数字A改成了B(1<=A,B<=N),现在他将这N个数字乱序告诉你,同时他也会告诉你现在这N个数字异或起来的结果X,请你快速找出这两个数字。

注意,本题时间限制O(N),空间限制O(1)

值得提醒的是空间o(1)不是只能开几个变量,而是你的数组必须是常数级别的。这里我们是知道n个数的异或和(出现偶数次的一定会在异或中被消去),然后找到异或和中第一个1(二进制中最低位出现一)(代表这两个数必定在这位不同),从而按照这一位是0或1将数据分成两部分。下面代码:

#include <stdio.h>
#include <algorithm>
using namespace std;
int N,X;
int Temp;
int T1,T2;
int Lowbit(int I)
{
   return I&-I;
}//lowbit操作,取出末尾1;
int main()
{
   int I,J,K;
   scanf("%d%d",&N,&X);
   X=Lowbit(X);
   for(I=1;I<=N;I++)
   {
   	scanf("%d",&Temp);
   	if(Temp&X)
   		T1^=Temp;
   	else
   		T2^=Temp;
   }
   printf("%d %d",min(T1,T2),max(T1,T2));
   return 0;
}

受到该题启发,我们可以改进一下算法:

对于这道题,我们不知道他的异或和,而且我们显然也不能将数据存储起来,求出异或和之后再进行操作。所以我们可以进行更一般的操作,对于int32位,我们可以开一个32*2的数组,f[i][0]表示在二进制第i位是0的异或和,f[i][1]表示二进制第i位是1的异或和,从而我们将数据分成了2类;
最后答案就是在这32位中寻找不会冲突的(即a,b两个数在二进制第i位不同)答案就是f[i][0],f[i][1](i位a,b二进制不同)。如何判断i,暴力从0到31扫,f[k][0],f[k][1]都不等于0即可,代码如下:

//结束后再发
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东风中的蒟蒻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值