第02节课
1. 安位异或交换两个数
如何不用额外变量交换两个数
代码展示:
static void swap(int[] arr, int i, int j) {
if(arr == null || arr.length < 2 || i == j) return;
arr[i] = arr[i]^arr[j];
arr[j] = arr[i]^arr[j];
arr[i] = arr[i]^arr[j];
}
2. 找出数组中唯一出现奇数次的数
一个数组中有一种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这种数
思路:
将数组中的所有数字异或,出现了偶数次的元素全部被异或调,剩下唯一的一个出现了奇数次的元素
代码展示:
static int printOddTimesNum1(int[] arr) {
int eor = 0;
for (int x : arr) {
eor ^= x;
}
return eor;
}
3. 提取整数最右侧的1
怎么把一个int类型的数,提取出最右侧的1来
思路:
一个数在Java中表示方法为补码,正数的补码为自己,负数的补码为反码+1,一个数按位与上自己的镜像数可以得到右侧的1的正数
代码展示:
static int rightOne(int x) {
return x & (-x)
}
4. 找出数组中出现奇数次的两个数(其他数都是偶数次)
一个数组中有两种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这两种数
思路:
- 首先把所有的数按位异或,最终得到的数x只是两个出现奇数次的数的异或结果
- 找到结果数x的最右非0位置的数y,用这个数y来区分原来的两个数
- 用数y可以把原数组分离成两个数组,每一个数组中只会出现一个出现奇数次的数
代码展示:
static int[] printOddTimesNum2(int[] arr) {
if(arr == null && arr.length < 2) {
return new int[]{-1, -1};
}
int tmp = 0;
for(int ele: arr) {
tmp ^= ele;
}
int rightOne = tmp & (-tmp);
int onlyOne = 0;
for(int ele: arr) {
if((ele & rightOne) != 0) {
onlyOne ^= ele;
}
}
return new int[] {onlyOne, tmp ^ onlyOne}
}
5. 数组中其他数都是出现了M次,找出唯一出现了K次的数
一个数组中有一种数出现K
次,其他数都出现了M
次,M>1
,K<M
。找到,出现了K
次的数,要求,额外空间复杂度O(1)
,时间复杂度O(N)
思路:
对于一个整数,计算机使用32bit表示,整数使用补码表示为32位bit位
如果将每一个整数的32个bit位分别累加,出现了M次的数,对应的二进制位和一定能别M整除,而出现了K次的则不能,因为有条件K<M
限制
代码展示:
static int kmNormal(int[] arr, int k, int m) {
if (arr == null || arr.length < k) {
return -1;
}
Map<Integer, Integer> map = new HashMap<>();
for (int element : arr) {
if (map.containsKey(element)) {
map.put(element, map.get(element) + 1);
} else {
map.put(element, 1);
}
}
for (Integer key : map.keySet()) {
if (map.get(key) == k) {
return key;
}
}
return -1;
}
public static int onlyKTimes(int[] arr, int k, int m) {
if(arr == null || arr.length == 0) return -1;
int[] cells = new int[32];
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < 32; j++) {
cells[j] += (arr[i] >> j);
}
}
int ans = 0;
for(int i = 0; i < 32; i++) {
if(cells[i]%m != 0) {
if(cells[i]%m == k) {
ans |= (1 << i);
} else {
return -1;
}
}
}
if(ans == 0) {
int count = 0;
for(int i = 0; i < arr.length; i++) {
if(arr[i] == 0) {
count++;
}
}
if (count != k) {
return -1;
}
}
return ans;
}