• 34.数组中2个只出现一次的数字[Find two numbers which appear once]


    【题目】

    一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

    【分析】

    这是一道很新颖的关于位运算的面试题。

    X^X = 0, X^0 =X。

    首先我们考虑这个问题的一个简单版本:一个数组里除了一个数字之外,其他的数字都出现了两次。请写程序找出这个只出现一次的数字。

    这个题目的突破口在哪里?题目为什么要强调有一个数字出现一次,其他的出现两次?我们想到了异或运算的性质:任何一个数字异或它自己都等于0。也就是说,如果我们从头到尾依次异或数组中的每一个数字,那么最终的结果刚好是那个只出现1次的数字,因为那些出现两次的数字全部在异或中抵消掉了。

    有了上面简单问题的解决方案之后,我们回到原始的问题。如果能够把原数组分为两个子数组。在每个子数组中,包含一个只出现一次的数字,而其他数字都出现两次。如果能够这样拆分原数组,按照前面的办法就是分别求出这两个只出现一次的数字了。

    我们还是从头到尾依次异或数组中的每一个数字,那么最终得到的结果就是两个只出现一次的数字的异或结果。因为其他数字都出现了两次,在异或中全部抵消掉了。由于这两个数字肯定不一样,那么这个异或结果肯定不为0,也就是说在这个结果数字的二进制表示中至少就有一位为1。我们在结果数字中找到第一个为1的位的位置,记为第N位。现在我们以第N位是不是1为标准把原数组中的数字分成两个子数组,第一个子数组中每个数字的第N位都为1,而第二个子数组的每个数字的第N位都为0。

    现在我们已经把原数组分成了两个子数组,每个子数组都包含一个只出现一次的数字,而其他数字都出现了两次。因此到此为止,所有的问题我们都已经解决。

    【代码】

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
     

    unsigned int FindFirstBitIs1(int number)
    {
        
    // 110 --->n=1 (start from 0)
        int n = 0;
        
    while(((number >> n) & 1) == 0 && n < 32)
        {
            n++;
        }
        
    return n;
    }

    bool IsBit1(int number, unsigned int indexBit)
    {
        
    // 110,2---> true; 100,2--->false
        int temp = 1 << indexBit;
        
    return number & temp;
    }

    void FindNumbersAppearOnce(int data[], int length, int &num1, int &num2)
    {
        
    if(NULL == data || length < 2)
            
    return;

        
    // get the exclusive or result of array
        int resultExclusiveOR = 0;
        
    for (int i = 0; i < length; ++i)
        {
            resultExclusiveOR ^= data[i];
        }

        
    // find the index of first bit 1 in resultExclusiveOR
        int indexBit = FindFirstBitIs1(resultExclusiveOR);
        num1 = num2 = 
    0;
        
    for(int j = 0; j < length; ++j)
        {
            
    // divide numbers in data into 2 groups:
            // numbers in group1: the indexBit number is 1
            // numbers in group2: the indexBit number is 0
            if (IsBit1(data[j], indexBit))
            {
                num1 ^= data[j];
            }
            
    else
            {
                num2 ^= data[j];
            }
        }
    }

     【参考】

    http://zhedahht.blog.163.com/blog/static/2541117420071128950682/

    http://blog.csdn.net/maoxunxing/article/details/11386407

    http://zhedahht.blog.163.com/blog/static/25411174201283084246412/

    http://blog.csdn.net/wuzhekai1985/article/details/6704794

    个人学习笔记,欢迎拍砖!---by hellogiser

    Author: hellogiser
    Warning: 本文版权归作者和博客园共有,欢迎转载,但请保留此段声明,且在文章页面明显位置给出原文连接。Thanks!
    Me: 如果觉得本文对你有帮助的话,那么【推荐】给大家吧,希望今后能够为大家带来更好的技术文章!敬请【关注】
  • 相关阅读:
    。【自学总结 2】------3ds Max 菜单
    。【自学总结 1】------3ds Max 界面
    。求推荐一个usb集线器的购买网址
    (翻译)Importing models-Models
    (翻译)Importing models-FBX Importer, Rig options
    [游戏开发-学习笔记]菜鸟慢慢飞(18)-迷宫
    [游戏开发-学习笔记]菜鸟慢慢飞(17)- c#-委托简记(匿名方法,Lambda表达式)
    [游戏开发-学习笔记]菜鸟慢慢飞(16)- Unity3D-Android插件问题集锦
    [游戏开发-学习笔记]菜鸟慢慢飞(15)- Unity3D-图片压缩
    [游戏开发-学习笔记]菜鸟慢慢飞(14)- ScrollView刷新
  • 原文地址:https://www.cnblogs.com/hellogiser/p/3738909.html
Copyright © 2020-2023  润新知