异或^运算——找到数组中为奇数个数的元素
Posted 默辨
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了异或^运算——找到数组中为奇数个数的元素相关的知识,希望对你有一定的参考价值。
文章目录
题目1(出现奇数次的元素只有一个)
给出指定数组中,查找数组中为奇数个的元素(这样的元素只有一个,其余均为偶数)
arrs = 1,1,5,2,7,5,2,5,7
这里同样可以借助异或^的特性:相同为0,不同为1。也可以理解为,与0异或就是其本身,与自己异或为0
即代码可以写成
int retNum
for (int arr : arrs)
retNum ^= arr;
即下面的逻辑可以表示为
retNum
= 1^1^5^2^7^5^2^5^7
= 1^1^2^2^5^5^5^7^7
= (1^1)^(2^2)^(5^5)^5^(7^7)
= 0^0^0^5^0
= 5
题目2(出现奇数次的元素有两个)
给出指定数组中,查找数组中为奇数个的元素(这样的元素有两个,且互不相等,其余均为偶数)
arrs = 1,1,5,2,7,5,2,5,7,7
假设这两个数字分别为a和b,我们就可以得到
retNum = a^b
既然a不等于b,那么自然a和b的某一位一定不相同,我假设这个位置为x。
x = retNum & (~retNum + 1);
即在整个arrs数组的所有数中,x位为1的次数(0也同样开)中一定包含a或者b其中一个,该步只是为了将arrs数组中的a和b分。将包含a的这部分数据进行异或运算。如果两个数相同,其x位置的数字也相同,即异或后就会剩下a或者b
我们假设剩下的是a,就能得到下面的结果
retNum2 = a
次数得到b只需要将retNum和retNum2再次进行异或就可以了
b = retNum ^ retNum2 = a^b^a = (a^a)^b = 0^b = b
此时就可以得到出现奇数次的两个数据
最后代码合起来如下:
public static void printTwoNum(int[] arr)
int retNum = 0,
int retNum2 = 0;
// 1、获取a^b的结果
for (int arr : arrs)
retNum ^= arr;
// 2、找到a和b从右往左第一次出现不相同的二进制位下表
int x = retNum & (~retNum + 1);
for (int arr : arrs)
// 3、a和b在x位置上,必然是一个是1,一个是0,该方法就能将a和b分开
if ((arr & x) != 1)
// 4、将ab区分开后,再次异或,最后得到的结果就一定是被孤单出来的一个数据(整个类比题目1的概念)
retNum2 ^= arr;
// retNum2 = a或者b
// retNum ^ retNum2 = 异或一下就是另一个数据
System.out.println(retNum2 + " " + (retNum ^ retNum2));
以上是关于异或^运算——找到数组中为奇数个数的元素的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode Algorithm 540. 有序数组中的单一元素
LeetCode Algorithm 540. 有序数组中的单一元素