/*******************************************************************
Copyright(c) 2016, Tyrone Li
All rights reserved.
*******************************************************************/
// 作者:TyroneLi
//
/*
Q:
找出數組中只出現一次的數字:
一個整型數組中除了兩個數字以外,其他的數字都出現了兩次,找出這兩個
只出現一次的數字,要求時間複雜度是O(n),空間複雜度是O(1)。
S:
1. 對於這樣的數組,只有一個數字出現了一次,其他的數字都出現了兩次,如何
找出這個數字呢?我們可以從頭到尾遍歷這個數組,每個遍歷一個數字都做亦
或操作,那麼根據亦或操作結果,最後得到的就是這個只出現一次的數字。對
於兩個只出現一次,其他的數字都出現兩次的數組,考慮如何劃分數組使得劃
分出每個子數組只包含出現一次的數字,其他的數字都出現了兩次?也是從頭
到尾亦或遍歷數組,此時得到的結果是兩個只出現一次的不同的數字的亦或結
果,則可以根據這個結果中的某一位爲是否爲1,把整個數組劃分成一個子數組
這一位是1,另一個子數組這一位是0.
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
unsigned int findFirstDiffBitIndex(int num)
{
int rstIndex = 0;
while(((num & 1) == 0) && rstIndex < (8*sizeof(int)))
{
num >>= 1;
++rstIndex;
}
return rstIndex;
}
bool isBitOf1(int num, int index)
{
if(index < 0)
return false;
num >>= index;
return (num & 1);
}
void findTwoDiffNums(int*data, int length, int*num_1, int*num_2)
{
if(data == nullptr || length < 2)
return;
int rstNumOfFirst = 0;
for(int i = 0; i < length; ++i)
rstNumOfFirst ^= data[i];
unsigned int firstDiffBit1 = findFirstDiffBitIndex(rstNumOfFirst);
// std::cout << "rstNumOfFirst : " << rstNumOfFirst << " firstDiffBit1 : " << firstDiffBit1 << std::endl;
*num_1 = 0;
*num_2 = 0;
for(int i = 0; i < length; ++i)
{
if(isBitOf1(data[i], firstDiffBit1))
(*num_1) ^= data[i];
else
(*num_2) ^= data[i];
}
}
void test_1()
{
std::cout << "Test 1" << std::endl;
int data[] = {1,1,2,2,3,4,5,5};
int num_1 = 0;
int num_2 = 0;
findTwoDiffNums(data, 8, &num_1, &num_2);
std::cout << "Two result : 3 4, Get : " << num_1 << " " << num_2 << std::endl;
}
void test_2()
{
std::cout << "Test 2" << std::endl;
int data[] = {1,1,2,2,4,4,5,5};
int num_1 = 0;
int num_2 = 0;
findTwoDiffNums(data, 8, &num_1, &num_2);
std::cout << "Two result : 3 4, Get : " << num_1 << " " << num_2 << std::endl;
}
void test_3()
{
std::cout << "Test 3" << std::endl;
int data[] = {1,1,2,3};
int num_1 = 0;
int num_2 = 0;
findTwoDiffNums(data, 4, &num_1, &num_2);
std::cout << "Two result : 2 3, Get : " << num_1 << " " << num_2 << std::endl;
}
void test_findTwoDiffNums()
{
test_1();
test_2();
test_3();
}
int main(int argc, char**argv)
{
test_findTwoDiffNums();
return 0;
}