/*******************************************************************
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;
}