【算法】求数组中出现了奇数次的一种/俩种数(异或运算)

左程云算法与数据结构课 https://www.bilibili.com/video/BV13g41157hK?p=2&spm_id_from=pageDriver

题目描述

在一个数组中,

(1)有一种数出现了奇数次,其余数出现了偶数次,求出现了奇数次的那种数。

(2)有俩种数出现了奇数次,其余数出现了偶数次,求出现了奇数次的俩种数。

题解

(1)一批数进行异或,与异或的顺序无关。

对数组的所有数进行异或,出现偶数次的数进行异或之后是0,出现奇数次的那种数异或之后还是那个数,所以最终异或结果是出现奇数次的那种数。

例如:数组[1,1,2,3,4,2,3,1,4]中除了1出现了奇数次外其余数均出现了偶数次,对数组元素进行异或,1^1^2^3^4^2^3^1^4=1^1^1^2^2^3^3^4^4=1

public static void printOddTimesNum1(int[] arr) {
    int eor = 0;
    for (int cur : arr) {
        eor ^= cur;
    }
    System.out.println(eor);
}

(2)假设出现了奇数次的俩种数分别是a和b。

对数组元素进行异或,最终结果是a^b。

由于a不等于b,故a^b的二进制中至少有一位为1,假设是第n位为1。

对数组中第n位为1的元素进行异或(以第n位是否为1,可以把数组分成两份,a和b分别落于这两份之中),则结果为出现了奇数次的俩种数中的一种,然后让它和a^b进行异或,则可以求出另一种出现了奇数次的数。

public static void printOddTimesNum2(int[] arr) {
    int eor1 = 0,eor2 = 0;
    for (int cur : arr) {
        eor1 ^= cur;
    }
    //eor1 = a ^ b
    //eor1!=0,其二进制中至少有一个位置为1
    // 提取出最右的1
    int rightOne = eor1 & (~eor1+1);
    for (int cur : arr) {
        if ((cur & rightOne) == 1) {  //只有第n位是1的才进行异或
            eor2 ^= cur;
        }
    }
    System.out.println(eor2 + " " + (eor1 ^ eor2));
}
posted @   hzyuan  阅读(171)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)

喜欢请打赏

扫描二维码打赏

支付宝打赏

点击右上角即可分享
微信分享提示