一 基本概念
定义: 位运算中, 相同为 0,不同为 1,即 1^0=1
实际可以记为 无进位相加.
二 性质
性质一: 0^N == N
N^N == 0 (N为整数)
性质二: 满足交换律和结合律
A^B=B^A
(A^B)^C=A^(B^C)
三 演练
1. 交换两个数
private void swap(int[] arr, int i, int j) {
arr[i] = arr[i] ^ arr[j]; //
arr[j] = arr[i] ^ arr[j]; // arr[i] ^ arr[j] ^ arr[j]=arr[i] ^ 0=arr[i]
arr[i] = arr[i] ^ arr[j]; // arr[i] ^ arr[j] ^ arr[j]=0 ^ arr[j]=arr[j]
}
2. 奇数次与偶数次问题
问题描述: 一个数组中有一种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这种数
/**
* 查找出奇数次的数
*/
public int findOddTimesNumber(int[] arr) {
int ans = 0;
for (int i = 0; i < arr.length; i++) {
ans ^= arr[i];
}
return ans;
}
3. 提取最右位的 1
/**
* 原值: 0 1 0 1 0 0 0 0
* 取反: 1 0 1 0 1 1 1 1
* +1 : 1 0 1 1 0 0 0 0
* &= : 0 0 0 1 0 0 0 0
*/
public int findRightBit1(int num) {
// return num & (~num + 1); //取反后+1
return num & (-num); //负值
}
4. 奇数次与偶数次问题 Plus
问题: 一个数组中有两种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这两种数
分析:
- 假设这两个出现奇数次的数位 a,b ;
- 将所有数做异或操作,得到的值肯定为 a^b;
- 找到最后一位 1 所在的位置 index , 即 a 和 b 在该位一个为 0,一个为 1
- 将数组所有的数字分成两类,分类标准为 index 位是否为 1
- 分别对两组数据做累计异或得到两个值分别为 a 和 b
public void findOddTimes2Number(int[] arr) {
//1.所有数据异或,得到a^b
int ab = 0;
for (int i = 0; i < arr.length; i++) {
ab ^= arr[i];
}
System.out.println(ab);
//2.找到最后一位为1的位置
int rightBit1 = findRightBit1(ab);
System.out.println(rightBit1);
//3.根据这个位置将数组分为两组
int a = 0;
for (int i = 0; i < arr.length; i++) {
if (0 == (arr[i] & rightBit1)) {
a ^= arr[i];
}
}
System.out.println(a);
System.out.println(a^ab);
}
5. 数组中一种数出现 K 次,其他数都出现 M 次
问题: 一个数组中有一种数出现了 K 次,其他数都出现了 M 次,M>1,K<M, 要求找到这个出现 K 次的数,时间复杂度为 O(N),额外空间复杂度为 O(1)
分析:
- 如果一个数出现 M 次,则他的每一位都应该出现 M 次
- 将数组中所有数的每一位出现的次数累加,存入 32 位的数组 arr 中
- arr 中每一个 index 处的数如果时 M 倍数,则说明这位数不是我们要找的数
- 如果 index 处的数不是 M 倍数,则这一位时我们要找的数
- 遍历 arr 就可以组装出这个出现 K 次的数
public static int onlyKTimes(int[] arr, int k, int m) {
int[] t = new int[32];
// t[i] i位置的1出现了几个
for (int num : arr) {
for (int i = 0; i < 32; i++) {
t[i] += (num >> i) & 1;
}
}
int ans = 0;
for (int i = 0; i < 32; i++) {
if (t[i] % m != 0) {
if (t[i] % m == k) {
//出现k次,说明这个位置是我们要找的
ans |= (1 << i);
} else {
return -1;
}
}
}
//ans为0时,需要特别判断
if (ans == 0) {
int count = 0;
for (int num : arr) {
if (num == 0) {
count++;
}
}
if (count != k) {
return -1;
}
}
return ans;
}
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于