常见面试题 - 异或运算的算法应用

1 交换数据元素上的应用

请参考这里

2 其他的算法应用:

2.1 问题描述

(1)在一个一维数组中,有n个元素,其中只有一种数有奇数个,其他的种类的数字都有偶数个,请找出这个数

    public static int find_one_num(int arr[])
    {
            int eor = 0;
            for(int i = 0; i < arr.length; i++)
            {
                eor ^= arr[i];
            }
            return eor;
    }


分析: 时间复杂度为O(n),空间复杂度为O(1)

(2)在一个一维数组中,有n个元素,其中有两种数出现了奇数次,其他的种类的数字都有偶数个,请找出这两种数

  public static void find_oddTimesNum2(int arr[])
    {
        int eor = 0;
        // 生成一个eor变量,将其依次与数组中的每一个元素进行异或操作,得到一个结果,其结果为两个两种数字的异或结果
        for (int cur : arr)
            eor ^= cur;
        
        // 生成变量,存放这两种数中的其中一种
        int onlyOne = 0;
        /*
         * 找到eor中最后一位为1的bit位
         * 为什么要写这行代码? 假设这两种数分别为a和b,a != b, 则a ^ b的二进制串中至少有一位等于1,这一位1,
         * 就相当于a和b的二进制串中的该位上的值要么分别为1和0,要么分别为0和1,因为她们不同,我们只需要将rightOne和arr中的对应位
         * 置为1的元素进行 逻辑与 操作,如果结果为true,则执行onlyOne ^ arr[i],这一句必能帮助我们得到a或b中的一个元素,
         * arr[i]与onlyOne发生异或操作的子集中,必然包含了a或者b以及其他的出现了偶数次的元素,因为0与出现偶数个元素进行异或必然为0,所以我们仍然能得到目标结果
        */
        int rightOne = eor & (~eor + 1);
        // 进行第二轮遍历,
        for(int i = 0; i < arr.length; i++)
            // 当扫描到当前元素的时候,如果最右边的1所在位置和rightOne所在的位置相同,则将onlyOne和arr[i]元素进行异或操作,遍历结束会得到一个其中的这两种数中的某一个,
            if ((rightOne & arr[i]) == 0) // if ((rightOne & arr[i]) == rightOne) 这里的rightOne不能为1
                onlyOne ^= arr[i];
        System.out.println("onlyOne: " + onlyOne + ", onlyOne ^ eor: " + (onlyOne ^ eor));
    }

时间复杂度O(n),空间复杂度O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值