栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

讲清楚-异或运算之找奇数个数字问题-java

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

讲清楚-异或运算之找奇数个数字问题-java

异或运算之找奇数个数字问题
  • 异或运算
    • 异或性质
    • 异或执行结果
  • 找奇数个数字问题
  • 解题思路
  • 具体 java 代码举例实现

异或运算 异或性质
  • 相等为0,不等为1.
  • 异或满足交换律:a ^ b = b ^ a
  • 异或满足结合律:a ^ b ^ c = a ^ (b ^ c) = (a ^ b) ^ c;
  • 0 ^ 任何数 = 任何数本身
  • 任何数 ^ 任何数 = 0
异或执行结果
数1数2异或结果
110
101
000
011
找奇数个数字问题

问1:有一组数,只有一种数字是奇数个,其他都是偶数个,请找出这种数字是多少
如:5, 5, 5, 2, 2, 3, 3, 4, 4, 5, 5
结果是 5
问2:有一组数,只有两种数字是奇数个,其他都是偶数个,请找出这两种数字分别是多少
如:5, 5, 5, 2, 2, 3, 3, 4, 4, 5, 5, 2
结果是 2 和 5

解题思路

问题1:根据异或的交换律的性质,将所有的数异或就可以将偶数个的数异或为 0,剩下的就是奇数个的数字
问题2:

  1. 与问题1一样,先异或所有的数得到a ^ b
  2. 再通过取非+1再与运算本身(e & (~e + 1),这里的 e = a ^ b),得到两个奇数个数字的最右(后)边的不同位 rightOnlyOne
  3. 有了 a 与 b 之间的区分位之后,再把所有的数据此分组为 与运算 rightOnlyOne 为 0 和 1的两组,以此将a 和 b分开,这就又回到了问题1,从而得到两个奇数个数的数字
具体 java 代码举例实现
public class EvenTimeOddTimes {

    
    public static void printOddTimesNum(int[] array) {
        // 0 ^ 任何数 = 任何数本身
        int e = 0;
        // 异或计算不在乎数字执行先后的顺序,相同的数字异或计算等于 0,所以剩下的一定是奇数个的数字
        for (int a : array) {
            e ^= a;
        }
        System.out.println("奇数个数字为: " + e);
    }

    
    public static void printOddTimesNum2(int[] array) {
        int e = 0;
        // 第一个奇数个数字
        int a = 0;
        // 第二个奇数个数字
        int b = 0;
        // 同第一个方法
        for (int j : array) {
            // 获得的 e = a ^ b
            e ^= j;
        }
        // 获得 a ^ b 的结果的最后(右)的一位 1
        int rightonlyOne = e & (~e + 1);
        for (int r : array) {
            // 所有与 rightonlyOne 与运算之后为 0 的数字分为一组进行异或运算
            // 因为偶数个的数字会在异或运算中清零,而 rightonlyOne 是 a 和 b 的区别位(一个为0一个为1) ,所以只有 a 或者 b在这一组,另一在 r & rightOnlyOne) == 1 那一组
            if ((r & rightOnlyOne) == 0) {
                // 这里就可以得到 第一个奇数个的数字 ,用 a 表示
                a ^= r;
            }
        }
        //  a ^ e = a ^ a ^ b = b ,也就是另一个奇数个的数字
        b = a ^ e;
        System.out.println("第一种奇数个数字是:" + a + " 第二种奇数个数字是:" + b);
    }

    public static void main(String[] args) {
        int[] array = {5, 5, 5, 2, 2, 3, 3, 4, 4, 5, 5};// 5
        printOddTimesNum(array);
        int[] array2 = {5, 5, 5, 2, 2, 3, 3, 4, 4, 5, 5, 2};//2  5
        printOddTimesNum2(array2);
    }

}

结果

奇数个数字为: 5
第一种奇数个数字是:2 第二种奇数个数字是:5
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/353737.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号