《算法营01》
异或求数组中唯一出现两次的数
废话不多说,直接上代码(解释见下文):
//异或求数组中唯一出现两次的数
#include <iostream>
#include<stdlib.h>
#include<time.h>
using namespace std;
int main()
{
system("color F0");
srand((unsigned int)time(NULL));
int c[11]={0,1,2,3,4,5,6,7,8,9},x=0;
c[10]=rand() % 10 ;
cout<<"数组的各元素为:"<<endl;
for (int i=0;i<11;i++)cout <<c[i]<<" ";
//核心代码
for (int i=1;i<10;i++) x=x^i;
for (int i=0;i<11;i++) x=x^c[i];
//
cout<<endl<<endl<<"异或求得数组中唯一出现两次的数是:"<<endl<<" "<<x<<endl<<endl;
system("pause");
return 0;
}
解释1:
1.原理:任何数 异或其本身 得到的结果都为0;两个不相同的数异或得到的结果为1;
任何数和0异或都得到其本身。
2.不难想到,若让待求数组中其他元素个数变为偶数2,而 数组中唯一出现两次的数 的个数变成奇数3;那么异或后,其他元素均为0,而只留下一个“数组中唯一出现两次的数”。
3.故可引用一个 包含原数组所有元素但无重复的新数组 与 原数组 进行异或就能得到: 数组中唯一出现两次的数
解释2:
异或可以存在交换律,即:0 ^ 1^ 2 ^ n ^ 3 ^ 4 ^ n ^ 5 == 0 ^ 1^ 2 ^ 3 ^ 4 ^ 5 ^ (n ^ n);
1.定义一个变量 x,一个变量T; 令x与 包含原数组所有元素但无重复的新数组 进行异或 得到一个数T;
x ^ ( 0 ^ 1^ 2 ^ 3 ^ n ^ 4 ^ 5) = T;
2.再让T 与原数组异或即可求得 数组中唯一出现两次的数;
T ^ ( 0 ^ 1^ 2 ^ 3 ^ n ^ 4 ^ 5) ^ n = n;
即:T ^ T ^ n = n;
代码运行结果如图所示:
后文:
1. 此方法不足之处:
必须知道数的取值范围,且是连续的一组数
否则只能开辟辅助存储空间,暴力计算每个元素的个数
2.其他数字个数均为两个,找出落单的数
也是同样使用异或,只要定义变量x = 0;
让 x 与所有数均异或一次,所得结果即为 落单的数
(此方法不足之处同上)。