给定一个整数数组nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次,找出只出现一次的那两个元素。时间复杂度要求为O(n),空间为O(1);
自己的做法
public static int[] singleNumber(int[] nums) {
HashSet<Integer> set = new HashSet<>();
for (int num: nums) {
if (set.contains(num)) {
set.remove(num);
} else {
set.add(num);
}
}
int[] result = new int[2];
int i = 0;
for (int n : set) {
result[i++] = n;
}
return result;
}
位运算
public static int[] singleNumber1(int[] nums) {
/*
* 这个题目使用位运算很合适,主要是异或计算符
* 1、任何数与0异或,结果都是原来的数
* 2、任何数与自身异或,结果为0
* */
int all = 0;
for (int num : nums) {
all ^= num;
}
//因为all是两个只出现一次的数字异或的结果,所以找到最低位为1的,作为分界点,
//为1说明这两个数字在这个位上 一个是0,一个是1,那么用这个第i位去分组,为0的在一组,为1的在另外一组
//这样在两个组里面分别找出来两个不同的数字
int div = 1;
while ((div & all) == 0) {
div <<= 1;
}
int a = 0, b = 0;
for (int n : nums) {
if ((div & n) != 0) {
a ^= n;
} else {
b ^= n;
}
}
return new int[]{a, b};
}