剑指offer-找出数组中只出现一次的数字

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章