算法-异或与相关算法题解析

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

例如:异或、与、取反等在算法题中可作为高效的一种运算手段解决某些算法问题


`提示:以下是本篇文章正文内容,有两个算法题做参考

一、异或运算,在二进制上相同数异或为0,不同数异或为1

1.一堆数组,只有一个数出现奇数次,找到这个数?

示例:数组{1,2,3,1,2,3,5,5,5},我们要最终通过代码找到只出现奇数次的数5

代码如下(示例):

/**
 * 一堆数组,只有一个数出现奇数次,找到这个数
 */
public class Demo1 {

    /**
     * 异或相同的为0 不同的为1
     * 那么所有的数异或出来的值就是出现奇数次的这个数
     */
    public static void main(String[] args) {
        // 0异或所有不是本身的数为那个数
        int temp = 0;
        int [] arr = new int[]{1, 2, 3, 1, 2, 3, 5};
        for (int cur : arr) {
            temp ^= cur;
        }
        System.out.println(temp);
    }
}

2.一堆数组,只有两个数出现奇数次,其余数出现偶数次,找到这两个数?

代码如下(示例):

/**
 * 一堆数组,只有两个数出现基数次,其余数出现偶数次,找到这两个数
 */
public class Demo2 {

    /**
     * 异或相同的为0 不同的为1
     * 1.所有数异或结果为a^b
     * 2.又因为ab两个数不相同,所以在某一位上肯定不一样,一个为1,一个为0,按照这个划分可以划分为存在a,b的两个数组
     * 3.把上面某一方数组异或结果为a或者b
     * 4.再与1操作值异或得到另一个数
     */
    public static void main(String[] args) {
        // 得到a^b
        int temp = 0;
        // a或者b
        int one = 0;
        int [] arr = new int[]{1, 2, 1, 3, 1, 2, 1, 3, 5, 9};
        for (int cur : arr) {
            temp ^= cur;
        }
        one = temp;

        // 取a^b二进制最右侧的1的数
        int rightOne = one & (~one + 1);
        for (int cur : arr) {
            // 如果与运算结果为rightOne,则代表当前遍历的数在二进制上该位置为1
            if ((cur & rightOne) == rightOne) {
                one ^= cur;
            }
        }
        System.out.println("一个数为:" + one);
        System.out.println("另一个数为:" + (temp ^ one));
    }
}

分析过程:
a = 5的二进制为0101
b = 9的二进制为1001
one = a^b为1100
~one = ~(a^b)为0011
~one + 1 = ~(a^b)+1为0100
one & (~one + 1) = (a^b) & (~(a^b) + 1)为0100
也就是说通过第三位为1或者0把数组分成了两个阵营,a,b肯定分别存在不同的阵营,遍历的数跟rightOne与运算如果等于rightOne那么该数在二进制上第三位肯定为1,最后把所有此特性的数异或运算得到的就是a或者b,那么另一个数只要再异或一次就行
比如temp=a ^ b、 one=a、temp ^ one = a ^ b ^ a=b


总结

以上就是今天要讲的内容,本文通过两个算法题简单介绍异或在运算中的一些运用,喜欢的小伙伴点赞收藏

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值