zoukankan      html  css  js  c++  java
  • 一个整形数组里除了两个数字以外,其他数字都出现了两次,找出这两个只出现一次的数字。

    用异或运算来解题,首先看一下异或的特点:

    1.0^0=0,0^1=1,1^0=1,1^1=0,即相同取0,不同取1,那么相同的两个整数异或结果为0,任何整数与0异或都等于其本身

    2.异或满足交换律,即a^b^c=a^c^b

    所以,将数组中的数从头到尾依次异或,出现偶数次的数异或都为0,最终结果是两个只出现一次的数字异或的结果,由于这两个数字不同,异或的结果一定不为0,即其二进制表示形式中一定存在某一位为1,找到第一个为1的位,假设是第N位,那么在对应的这一位上,这两个数一个为0,一个为1,根据第N位是否为1,将原数组分成两个子数组,这两个子数组分中都只包含一个只出现了一次的数,其他的数都出现了两次,两个子数组中的元素分别异或,就得到了两个只出现一次的数。

     1 #include<iostream>
     2 using namespace std;
     3 bool IsBit1(int num,unsigned int indexBit)   //判断num的第indexBit位是否为1,位数从0算起
     4 {
     5     num=num>>indexBit;   //将num的第indexBit移到末尾
     6     return(num&1);     //1除了第一位,其余为均为0,&操作结果必为0,决定结果的只是第indexBit位
     7 }
     8 
     9 unsigned int FindFirstBitIs1(int num)
    10 {
    11     int indexBit=0;
    12     while(num>0&&(num&1)==0)
    13     {
    14         indexBit++;
    15         num=num>>1;
    16     }
    17     return indexBit;
    18 }
    19 
    20 void FindNumsAppearOnce(int data[],int length,int &num1,int &num2)
    21 {
    22     if(length<2) return;
    23     int result=0;
    24     for(int i=0;i<length;i++)
    25         result=result^data[i];
    26     int indexBit=FindFirstBitIs1(result);
    27     num1=num2=0;
    28     for(int i=0;i<length;i++)
    29     {
    30         if(IsBit1(data[i],indexBit))   //根据第indexBit是否为1将数组分成两组,并进行异或
    31             num1=num1^data[i];
    32         else
    33             num2=num2^data[i];
    34     }
    35 
    36 }
    37 void main()
    38 {
    39     int a[10]={1,1,2,2,3,3,4,4,5,6};
    40     int num1,num2;
    41      FindNumsAppearOnce(a,10,num1,num2);
    42      cout<<num1<<" "<<num2;
    43 
    44 }

    结果:

  • 相关阅读:
    5
    4
    3
    crontab -e 报错(E518: Unknown option: foldenable)
    解决无法修改日志时间的问题(Local time zone must be set--see zic manual page 2019 )
    ping测试丢包率
    关闭SELinux
    iotop使用方法
    mysql的备份
    修改uid gid 的起始范围
  • 原文地址:https://www.cnblogs.com/mrlsx/p/5442643.html
Copyright © 2011-2022 走看看