题目:
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
分析:
我们可以先考虑一个稍微简单点的情况,一个整型数组里除了一个数字之外,其他的数字都出现了两次。这是上面题目的一个简化版本。我们只要能解决这个问题了,然后将上面题目中的数组按照某种规则分别分成两个只有一个数字出现一次的数组,就可以解决上面的题目。
所以,现在我们面临的是两个问题:
1.如何在一个整型数组中找到仅出现一次的那个数。
2.如何将题目中的整形数组分成两个只有一个数字出现一次的数组。
对于第一个问题,我们可以使用异或来解决,异或的性质是一个数异或自己本身就会消失,所以我们只有连续异或这个数组中的每个数字,最后异或出来的结果就是数组中仅出现一次的那个数。
第二个问题,如果我们将有两个仅出现一次的数字的数组中的每个元素都异或一次,那么异或的结果就是数组中仅出现一次的那两个数的异或结果,而这个结果肯定不为0,我们可以在这个结果数字中选取某一位,将题目中的数组分成这一位为0的和这一位不为0的两部分,分别对每一部分求解即可。
class Solution
{
public:
void FindNumsAppearOnce( vector<int> data, int* num1, int* num2 )
{
if ( data.empty() )
return ;
int resultExclusiveOR = 0;
for ( int i = 0; i < data.size(); ++i )
resultExclusiveOR ^= data[i];
unsigned int indexOf1 = FindFirstBitIs1( resultExclusiveOR );
*num1 = *num2 = 0;
for ( int j = 0; j < data.size(); j++ )
{
if ( IsBit1( data[j], indexOf1 ) )
*num1 ^= data[j];
else
*num2 ^= data[j];
}
}
unsigned int FindFirstBitIs1( int num )
{
int indexBit = 0;
while ( (( num & 1 ) == 0) && ( indexBit < 8*sizeof(int) ) )
{
num = num >> 1;
++indexBit;
}
return indexBit;
}
bool IsBit1( int num, unsigned int indexBit )
{
num = num >> indexBit;
return ( num & 1 );
}
};
int main( void )
{
Solution sos;
vector<int> array = { 2, 4, 3, 6, 3, 2, 5, 5 };
int num1 = 0, num2 = 0;
sos.FindNumsAppearOnce( array, &num1, &num2 );
cout << num1 << num2 << endl;
return 0;
}
482

被折叠的 条评论
为什么被折叠?



