• 一个数组中有两种数出现了奇数次,其他数都出现了偶数次,寻找这两个数


    1) 在一个数字序列中,有一个数出现了奇数次,其他数都出现了偶数次,找到这个奇数次的数

    2) 一个数组中有两种数出现了奇数次,其他数都出现了偶数次,寻找这两个奇数次的数

    1.异或运算:
    简单来讲,就是相同为0,不同为1:
      1^1=0
      0^0=0
      1^0=1
      0^1=1
    此外,异或运算符合两个性质:交换律和结合律,也就是说
    a ^ b = b ^ a
    a ^ b ^ c = a ^ (b ^ c) = (a ^ b) ^ c;

    2.问题分析
    看过问题一的小伙伴都知道了异或运算的原理,在这里就不多说了。
    我们还是将这个序列的所有数都异或一下,假设这两个奇数是a和b,那么就得到了一个数a^b.
    那么问题来了,如果知道a和b分别是多少呢?
    根据题干我们知道,a和b肯定不相等,因此,a^b != 0,既然它不等于0,那么在二进制上肯定有一位为1,我们根据上面提到的公式提取得到最右侧为1的那个数c。

    此外,a^b != 0,且最右侧有一位为1,只有0和1才能异或出来,那么我们可以断定,a和b在这一位上,肯定是一个为0,一个为1.

    我们都知道,这个数c有一个特征,只有一位为1,其他位置都为0.

    现在我们让c和数组arr中的所有元素进行相与,只有两个位置都为1,才能相与出来1。因此,这样我们可以把数组序列分为两类,一类是在这一位上为0的值,一类是在这一位上为1的值。

    最后,我们让(a^b)得到的值分别与这两类的值进行异或,消除掉那些偶数的值,剩下的就是这两个数。

    3.如何获取最右边的1

    寻找一个二进制数在最右侧的1,示例:
    c = 0110100
    从右往左看,c在倒数第三位上的数字为1,没错,我们就是要找这个数0000100,怎么做到呢?记住下面的这个公式:
    result=c&(~c+1))

    &运算: &运算中1&1=1,1&0=0,0&0=0

    !c = 1001011
    !c + 1 = 1001100
    c&(~c+1) = 0000100
    记住这个算式即可

    4.代码如下:

        //1)在一个数字序列中,有一个数出现了奇数次,其他数都出现了偶数次,找到这个奇数
        public static void printNumber(int[] arr){
            int eor = 0;
            for (int cur : arr){
           //把这个数组所有的数进行异或运算,即可得到这个奇数次的数 eor
    ^= cur; } System.out.println(eor); }   
      //2) 一个数组中有两种数出现了奇数次,其他数都出现了偶数次,寻找这两个数
    public static void printTwoNumber(int[] arr){ int eor = 0; for (int cur : arr){ eor ^= cur; }
         //一个数“与” 上这个数 “取反加一” 就可以得到最右边的1
    int rightOne = eor & (~eor + 1); int eor1 = 0;
         //获取到两个数中的其中一个(至于是哪一个不用管它,肯定会有一个)
    for (int cur : arr){
           //用最右边的1这个数来区分, &运算中1&1=1,1&0=0,0&0=0
    if ((cur & rightOne) != 0){ eor1 ^= cur; } } System.out.println(eor1 + " " +(eor1^eor)); }
  • 相关阅读:
    对C#泛型中的new()约束思考
    c语言位运算符
    最简单易懂的委托例子
    静态方法是否属于线程安全
    使用JS实现鼠标滚轮事件
    Google Map 自定义 infowindow
    firefox下对ajax的onreadystatechange的支持情况分析及解决
    xcode7和ios9下UIWebView不能加载网页的解决方法
    在iOS平台使用ffmpeg解码h264视频流(转)
    Mac下批量删除.svn文件
  • 原文地址:https://www.cnblogs.com/cdlyy/p/16442745.html
Copyright © 2020-2023  润新知