/*
题目出处:《剑指offer——名企面试官精讲典型题目》P211
题目:一个整型数组除了两个数字之外,其它的数字都出现了两次。请写程序找出这两个只出现一个的数字。要求时间复杂度是O(n),空间复杂度是O(1);
*/
/*
解题思路,这题是数组中除了一个数字外,其它的数字都出现两次的题目的变形,所以我们也应该从这个地方入手。如果只有一个数字,我们只需要用零去异或数组的所有数字,最后的结果就是那个落单的数字。
那么这题的,最后异或所得的结果是 两个落单的数字异或的结果,首先,这个结果肯定不会是0,不然它们就相等,不符合题目要求。既然不是零,我们从这个数字中找到它的二进制数中的随便一位不是零的位数,
那么就可以把这两个落单数字区分开了,就相当于是把这个数组分成的某个二进制位是否为1的两个数组。接着我们就可以按照一个数组所有数字都出现两次,只有一个数字出现一次的方法来做了。下面的解法是取异或结果的二进制数最右边的1的位置。
*/
#include<iostream>
using namespace std;
class TwoNumbersAppearOnce
{
public :
TwoNumbersAppearOnce (){};
~TwoNumbersAppearOnce(){};
void FindNumsAppearOnce(int data[], int length, int *numOne, int *numTwo)
{
if(data == NULL || length<2)
return ;
int i;
int result = 0;
for(i=0; i<length; ++i)
result = result ^ data[i];
int indexOf1 = FindFirstRightOf1(result);
*numOne = 0;
*numTwo = 0;
for(i=0; i<length; ++i)
{
if(isOne(data[i],indexOf1))
*numOne = *numOne ^ data[i];
else
*numTwo = *numTwo ^ data[i];
}
}
private:
int FindFirstRightOf1(int result)
{
int index = 0;
while((result & 0x1)==0 && index<sizeof(int)*8)
{
++index;
result = result>>1;
}
return index;
}
bool isOne(int numOne , int index)
{
numOne = numOne >>index;
if((numOne & 0x1))
return true;
return false;
}
};
int main()
{
TwoNumbersAppearOnce twoNumbersAppearOnce;
int arr[8] = {2,2,1,3,4,4,5,5};
int numOne;
int numTwo;
twoNumbersAppearOnce.FindNumsAppearOnce(arr,8, &numOne, &numTwo);
cout<<numOne<<" "<<numTwo<<endl;
return 0;
}
数组中只出现一次的数字升级版
最新推荐文章于 2024-06-01 07:27:22 发布