题目描述
一个整型数组里除了两个数字之外,其他的数字都出现了偶数次。请写程序找出这两个只出现一次的数字。
提交链接:点击
思路:
方法一:利用c++ STL的map集合,遍历一遍序列得到元素的次数,再访问取出即可,时间复杂度O(n)。
方法二:可以用位运算实现,如果将所有所有数字相异或,则最后的结果肯定是那两个只出现一次的数字异或
的结果,所以根据异或的结果1所在的最低位,把数字分成两半,每一半里都还有只出现一次的数据和成对出现的数据
这样继续对每一半相异或则可以分别求出两个只出现一次的数字
的结果,所以根据异或的结果1所在的最低位,把数字分成两半,每一半里都还有只出现一次的数据和成对出现的数据
这样继续对每一半相异或则可以分别求出两个只出现一次的数字
代码:
//方法一 class Solution { public: void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) { map<int,int> result; for(int i=0;i<data.size();i++){ result[data[i]]+=1; } int count=1; for(int i=0;i<data.size();i++){ if(result[data[i]]==1 && count==1){ count++; num1[0]=data[i]; continue; } else if(result[data[i]]==1 && count==2){ num2[0]=data[i]; break; } } } };
//方法二 class Solution { public: void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) { if(data.size()<2) return ; int result=0; for(int i=0;i<data.size();i++){ result^=data[i]; //得到两个不同数字的异或结果 } if(result==0) return ; int indexOf1=0; while((result&1)==0 && indexOf1<8*sizeof(int)){ result>>=1; //找到最开始的1,用来区分为两个不同的集合 indexOf1++; } *num1=*num2=0; for(int i=0;i<data.size();i++){ if(isBit1(data[i],indexOf1)){ *num1^=data[i]; }else{ *num2^=data[i]; } } } //判断该位是否为1 int isBit1(int number,int index){ number>>=index; return number&1; } };