|
请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。 - #include<iostream>
- using namespace std;
- int findFirstOne(int value);
- bool testBit(int value,int pos);
- int findNums(int array[],int length,int &num1,int &num2){
- if(length<2){return -1;}
- int ansXor=0;
- for(int i=0;i<length;i++)
- {
- ansXor^=array[i]; //异或
- }
- int pos=findFirstOne(ansXor);
- num1=num2=0;
- for(int i=0;i<length;i++)
- {
- if(testBit(array[i],pos))
- num1^=array[i];
- else
- num2^=array[i];
- }
- return 0;
- }
- int findFirstOne(int value)
- { //取二进制中首个为1的位置
- int pos=1;
- while((value&1)!=1)
- {
- value=value>>1;
- pos++;
- }
- return pos;
- }
- bool testBit(int value,int pos)
- { //测试某位置是否为1
- return ((value>>pos)&1);
- }
- int main(void)
- {
- int array[10]={1,2,3,4,5,6,4,3,2,1};
- int num1,num2;
- if(findNums(array,10,num1,num2)==0)
- cout<<num1<<" "<<num2<<endl;
- else
- cout<<"error"<<endl;
- return 0;
- }
复制代码
1、首先第一次遍历整个数组,找出不同的那两个数的异或后的结果,见下面这段代码. - for(int i=0;i<length;i++)
- {
- ansXor^=date[i]; //异或
- }
复制代码
2、找到异或结果中ansXor中用移位的方式找到第一个二进制数中为1的位置,这个很关键,找到这个位置后,说明在该位置上,这两个不同的数中,一个为0,一个为1,这个应该可以理解对吧? - int pos=findFirstOne(ansXor);
复制代码
我们把这个位置记为pos
3、然后再遍历一次数组,把这个数组分成两个子数组,pos位上为1的,和pos位上为0的 - for(int i=0;i<length;i++)
- {
- if(testBit(date[i],pos))
- num1^=date[i];
- else
- num2^=date[i];
- }
复制代码 这里借助了异或的原理,pos位置上为1的其它成双成对的数肯定也是为1的,同理,pos位上为0的时也一样。
|