zoukankan      html  css  js  c++  java
  • 【算法14】找出数组中两个只出现一次的数字

    【题 目】一个整型数组中除了两个数字外,其他的数字都出现两次。请找出这两个只在数组中出现一次的数字。要求时间复杂度O(n),空间复杂度O(1)。

    【思 路】首先我们考虑一个稍微简单点的情况:如果这个数组中只有一个数字出现且仅出现一次,其他数字都出现两次,我们应该怎么样找出这个数字呢?我们题目说数字出现两次有什么深意呢?我们很容易联想到异或运算,因为任何一个数字和自身异或的结果为0;知道了这点,我们就很容易知道,我们将所有的数字进行异或,其结果就是仅出现一次的数字,因为其他所有的数字都两两异或为0了。

      有了上面那个简单题目作为引子,我们很容易想到,如果我们将原题目的数组成功的分为两个子数组,而每个子数组恰好含有一个仅出现一次的数字,那么我们就可以根据上面的思路直接求解。怎么划分这两个子数组呢?

      我们仍然将原数组中的所有数字进行异或运算,容易知道,异或的结果实际上就是两个仅出现一次的数字的异或结果,因为这两个数字不相等,所以异或的结果肯定不为0,我们可以找到异或结果中,第一个为1的位,这说明在该位上,必然有一个数字为1,另一个数字在该为上为0;我们可以按照这个结果,对所有该位上为1的数字分为一组,而将该位上为0的位分为另一组,这样我们就成功的讲原问题转换为两个简单的子问题。再对子问题全部异或,即可获得两个仅出现一次的数字。按照这个思路,我们可以得到如下的代码:

     1 #include<iostream>
    2 #include<string>
    3 using namespace std;
    4
    5 //判断一个数number的第bitIndex位是否为1
    6 bool IsBit1(int number,unsigned int bitIndex)
    7 {
    8 number = number>>bitIndex;
    9 return (number & 1);
    10 }
    11
    12 //找到num中第一个位是1的位
    13 unsigned int FindFirstbitOf1(int num)
    14 {
    15 int bitIndex = 0;
    16 while(bitIndex < 32 && ((num & 1) == 0))
    17 {
    18 num = num>>1;
    19 bitIndex++;
    20 }
    21
    22 //该函数的另一种循环结构,完全等价
    23 /* for(bitIndex = 0;bitIndex < 32;++bitIndex,num = num>>1)
    24 {
    25 if((num & 1) ==1)
    26 break;
    27 }
    28 */
    29 return bitIndex;
    30 }
    31
    32 void FindNumbersAppearOnce(int data[],unsigned int length,int &num1,int &num2)
    33 {
    34 //无效输入
    35 if(data == NULL || length < 2)
    36 return;
    37
    38 //得到num1异或num2
    39 int resultOfBitOR = 0;
    40 for(int i = 0;i < length;++i)
    41 {
    42 resultOfBitOR ^= data[i];
    43 }
    44
    45 //找到num1^num2的结果中第一个为1的位
    46 unsigned int index = FindFirstbitOf1(resultOfBitOR);
    47
    48 num1 = 0;
    49 num2 = 0;
    50
    51 //将index位的取值是否为1分为两组
    52 //将每一组的全部数字做异或
    53 for(int j= 0;j < length;++j)
    54 {
    55 if(IsBit1(data[j],index))
    56 num1 ^= data[j];
    57 else
    58 num2 ^= data[j];
    59 }
    60
    61
    62 }
    63
    64 int main()
    65 {
    66 cout<<"Please Enter your ArrayLength:"<<endl;
    67 int arraylength = 0;
    68 cin>>arraylength;
    69
    70 int *array = new int[arraylength];
    71 cout<<"Please Enter the numbers in your Array:"<<endl;
    72 for(int k = 0;k < arraylength;++k)
    73 {
    74 cin>>array[k];
    75 }
    76
    77 int result1 = 0;
    78 int result2 = 0;
    79 FindNumbersAppearOnce(array,arraylength,result1,result2);
    80
    81 cout<<"the numbers appear once in your array are:"<<endl;
    82 cout<<result1<<"\t"<<result2<<endl;
    83
    84 return 0;
    85 }

      测试及运行结果如下:


    References:

    何海涛博客:http://zhedahht.blog.163.com/blog/static/2541117420071128950682/

    注:

    1)本博客所有的代码环境编译均为win7+VC6。所有代码均经过博主上机调试。

    2)博主python27对本博客文章享有版权,网络转载请注明出处http://www.cnblogs.com/python27/。对解题思路有任何建议,欢迎在评论中告知。

  • 相关阅读:
    Django-ORM和MySQL事务及三大范式介绍
    django-视图层与模板层
    django初步--+urls解析
    django前戏
    python web开发中跨域问题的解决思路
    MySQL显示ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (10061)解决方法
    xpath
    HTTP请求方法
    JavaScript 对象
    JavaScript 关键字
  • 原文地址:https://www.cnblogs.com/python27/p/2279980.html
Copyright © 2011-2022 走看看