2 Star 2 Fork 2

青石路 / qsl-project

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
ExclusiveORTest.java 4.83 KB
一键复制 编辑 原始数据 按行查看 历史
youzhibing 提交于 2021-12-24 17:50 . 汉诺塔
package com.lee.algorithm.eor;
/***
* 异或运算:位相同则为0,位不同则为1;也可称做无进位相加
* 异或运算规则:
* 0 ^ N = N
* N ^ N = 0
* N ^ M = M ^ N
* (N ^ M) ^ Y = N ^ (M ^ Y)
* @description: 异或 巧用
* @author : 青石路
* @date: 2021/11/18 14:12
*/
public class ExclusiveORTest {
public static void main(String[] args) {
int[] objArr = new int[]{1,2,3,4,5,6,1,2,3,4,5,6,6,6,1,2};
int[] oddTimesNum2 = findOddTimesNum2(objArr);
System.out.println("oddTimes num : " + oddTimesNum2[0] + ", " + oddTimesNum2[1]);
}
/**
*
* 不用额外的变量交换两个变量的值
* i != j, 否则会出问题(两个变量指向的是不同的两块内存区域)
* @author 博客园 @ 青石路
* @param arr
* @param i
* @param j
*/
public static void swapWithoutOtherVar(int[] arr, int i, int j) {
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
/**
* 已知一串数中,只有 1 个数字出现了奇数次,
* 其他数字都出现了偶数次,如何快速找到这个奇数次的数字
* 要求:时间复杂度:O(N), 空间复杂度 O(1)
* @author 博客园 @ 青石路
* @param arr
*/
public static int findOddTimesNum(int[] arr) {
int eor = 0;
for (int cur : arr) {
eor ^= cur;
}
return eor;
}
/**
* 已知一串数中,有 2 个数字出现了奇数次,其他数字都出现了偶数次,如何快速找到 2 个奇数次的数字
* 要求:时间复杂度:O(N), 空间复杂度 O(1)
* 分析:
* 假设出现了奇数次的数字是:a、b,a != b
* 所有数字都进行异或运算后,得到的结果是:int eor = a ^ b
* a != b,所以 eor != 0,那么 eor 肯定有某一个二进制位是 1
* @author 博客园 @ 青石路
* @param arr
*/
public static int[] findOddTimesNum2(int[] arr) {
int eor = 0;
for (int cur : arr) {
eor ^= cur;
}
// 此时 eor = a ^ b; a != b,所以 eor != 0,那么 eor 肯定有某一个二进制位是 1
// 取 eor 二进制最右(左)边的 1
int rightOne = eor & (~eor + 1); // rightOne 所有二进制位中只有一个 1 ,其他都是 0
int onlyOne = 0;
// int otherOne = 0;
for(int cur : arr) {
/**
* 通过 rightOne 将全部数据拆成两部分:cur & rightOne = 0 和 cur & rightOne != 0
* a、b 分别落在两侧,其他数字只会落在某一侧(并且是偶数个)
* 全部数据就被拆分成两个 findOddTimesNum 的数据模型了
*/
if ((cur & rightOne) == 0) {
onlyOne ^= cur;
} /*else {
otherOne ^= cur;
}*/
}
// System.out.println("onlyOne = " + onlyOne + ", otherOne = " + otherOne);
// onlyOne = a、b 中的某一个
// 另一个 = onlyOne ^ eor = onlyOne ^ (a ^ b)
return new int[]{onlyOne, onlyOne ^ eor};
}
/**
* 一串数字包含 n-1 个成员,这些成员是 1 到 n 之间的整数,
* 且没有重复,请找出缺少的那个数字
* 要求:时间复杂度:O(N), 空间复杂度 O(1)
* @author 博客园 @ 青石路
* @param arr
* @return
*/
public static int findMissNum(int[] arr) {
int sum = 0;
// 先求和,1 + 2 + ... + n
for (int i=1; i<=arr.length+1; i++) {
sum += i;
}
// 再逐个减去这串数字
for(int i=0; i<arr.length; i++) {
sum -= arr[i];
}
return sum;
}
/**
* 一串数字包含 n-1 个成员,这些成员是 1 到 n 之间的整数,
* 且没有重复,请找出缺少的那个数字
* 要求:时间复杂度:O(N), 空间复杂度 O(1)
* @author 博客园 @ 青石路
* @param arr
* @return
*/
public static int findMissNumPlus(int[] arr) {
int eor = 0;
for(int i=0; i<arr.length; i++) {
eor ^= arr[i] ^ (i+1);
}
eor ^= arr.length + 1;
return eor;
}
/**
* 一串数字包含 n+1 个成员,这些数字是 1 到 n 之间的整数,只有一个数字出现了两次,
* 其他数字都只出现一次,请找出重复出现的那个数字
* 要求:时间复杂度:O(N), 空间复杂度 O(1)
* @author 博客园 @ 青石路
* @param arr
* @return
*/
public static int findRepeatNum(int[] arr) {
int eor = 0;
int n = arr.length-1;
for(int i=0; i<n; i++) {
eor ^= arr[i] ^ (i+1);
}
eor ^= arr[n];
return eor;
}
}
1
https://gitee.com/youzhibing/qsl-project.git
git@gitee.com:youzhibing/qsl-project.git
youzhibing
qsl-project
qsl-project
master

搜索帮助