2107 二个奇数次
1.0 秒 131,072.0 KB
输入一个长度为n的数组,考虑所有不同的数字,有且只有2个数字出现了奇数次。
比如对于1 2 3 1 2 3 1 2,我们考虑所有不同的数字1 2 3,有且只有1,2出现了奇数次(均为3次)
输出这两个出现了奇数次的数字。
先输出这两个数字中较小的,再输出较大的。
1 <= n <= 100000
1 <= a[i] <= 10^9
输入
第一行一个整数n,
接下来一行n个整数,表示输入的数字。
输出
一行2个数字,表示出现了奇数次的数字,先输出小的,再输出大的。
输入样例
8
1 2 3 1 2 3 1 2
输出样例
1 2
解题思路:之前我们做过一个奇数次,即给定n个数,有且只有一个数出现了奇数次,输出这个数,在做那个题的时候直接一直异或运算就可以得到想要的数字(因为n^n等于0,而0和任何数异或都是数字本身,所以就很好求),这个题要求出现奇数次的两个数,肯定不能一直异或吧…思路:还是先将所有数异或在一起,最后一定会得到一个数,这个数是要求的两个数异或在一起,然后分成两组去求这两个数,具体怎么分呢?假设两个数异或在一起的二进制数R是110111000,我们知道异或以后1的位置就是两个数不一样的位置。我们进行这样一个操作:int lowbit=R&(-R),这个操作的用处在于找出最低位1的位置。R是110111000,而-R是001001000,(数字在计算机中是以补码的形式存储的)两个数&在一起,得出来的是1000,这就是两个数不同的地方最低位1的位置,我们分两组:这一位是1的一组,0的一组,然后异或在一起,就很容易得到了。代码实现:
#include <bits/stdc++.h>
using namespace std;
const int _max=1e5+5;
int s[_max];
int main()
{
int n,r=0;
int a=0,b=0;
cin>>n;
for(int i=0;i<n;i++)
cin>>s[i];
for(int i=0;i<n;i++)
r^=s[i];
int lowbit=r&(-r);//找最低位1的位置
for(int i=0;i<n;i++)
if(s[i]&lowbit)//分成两组分别异或
a^=s[i];
else
b^=s[i];
cout<<min(a,b)<<" "<<max(a,b)<<endl;
return 0;
}