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)