首页 > 代码库 > 找出三个只出现一次的数字 C语言实现
找出三个只出现一次的数字 C语言实现
题目:一个数组中有三个数字a、b、c只出现一次,其他数字都出现了两次。请找出三个只出现一次的数字。
分析:如果我们把数组中所有数字都异或起来,那最终的结果(记为x)就是a、b、c三个数字的异或结果(x=a^b^c)。其他出现了两次的数字在异或运算中相互抵消了。
我们可以证明异或的结果x不可能是a、b、c三个互不相同的数字中的任何一个。
由于x与a、b、c都各不相同,因此x^a、x^b、x^c都不等于0。
我们定义一个函数f(n),它的结果是保留数字n的二进制表示中的最后一位1,而把其他所有位都变成0。f(x^a)、f(x^b)、f(x^c)的结果均不等于0。
f(x^a)^f(x^b)^f(x^c)的结果的二进制中至少有一位是1。假设最后一位是1的位是第m位。那么x^a、x^b、x^c的结果中,有一个或者三个数字的第m位是1。
可以证明x^a、x^b、x^c的三个结果第m位不可能都是1。
因此x^a、x^b、x^c三个数字中,只有一个数字的第m位是1。于是我们找到了能够区分a、b、c三个数字的标准。这三个数字中,只有一个数字满足这个标准,而另外两个数字不满足。一旦这个满足标准数字找出来之后,另外两个数字也就可以找出来了。
#include<stdio.h> static int lastBitOf1(int x) { return x&-x; } static void getTwoUnique(int a[],int n,int b[]) { int xorResult=0; for(int i=0;i<n;++i) xorResult^=a[i]; int diff=lastBitOf1(xorResult); int first=0; int second=0; for(int i=0;i<n;++i) { if(diff&a[i]) first^=a[i]; else second^=a[i]; } b[1]=first; b[2]=second; } void getThreeUnique(int a[],int n,int b[]) { if(n<3) return ; int xorResult=0; for(int i=0;i<n;++i) { xorResult^=a[i]; } int flags=0; for(int i=0;i<n;++i) { flags^=lastBitOf1(xorResult^a[i]); } flags=lastBitOf1(flags); int first=0; for(int i=0;i<n;++i) { if(flags==lastBitOf1(xorResult^a[i])) { first^=a[i]; } } b[0]=first; for(int i=0;i<n;++i) { if(a[i]==first) { int t=a[i]; a[i]=a[n-1];//数组的最后一个元素 a[n-1]=t; break; } } getTwoUnique(a,n-1,b); } int main(int argc, char *argv[]) { int a[]={2,2,3,3,4,4, 5,6,7, 8,8}; int b[3]; getThreeUnique(a,11,b); for(int i=0;i<3;++i){ printf("%d",b[i]); if(i+1!=3) printf(" "); } printf("\n"); return 0; }
结果是正确的
找出三个只出现一次的数字 C语言实现
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。