1.题目
LeetCode: 260. 只出现一次的数字 III
【medium】
2.解题
*方法一:位运算 - 异或
两个不相等的元素在位级表示上必定会有一位存在不同。
将数组的所有元素异或得到的结果为不存在重复的两个元素异或的结果。
diff &= -diff 得到出 diff 最右侧不为 0 的位,也就是不存在重复的两个元素在位级表示上最右侧不同的那一位,利用这一位就可以将两个元素区分开来。
换句话说,
通过diff &= -diff 得到出 diff 最右侧不为 0 的位,通过这一位我们可以把数组中所有元素分成两组,然后两组元素分别进行异或操作随后剩下的两个元素即为答案。
java:
class Solution {
public int[] singleNumber(int[] nums) {
int[] res = new int[2];
int diff = 0;
for (int num : nums) diff ^= num;
diff &= -diff;
for (int num : nums) {
if ((num & diff) == 0) res[0] ^= num;
else res[1] ^= num;
}
return res;
}
}
时间复杂度:O(n)。
空间复杂度:O(1)。
方法二:哈希表
遍历数组,如果哈希表中没有当前元素则存入否则删除,哈希表中剩下的元素即为答案。
java:
class Solution {
public int[] singleNumber(int[] nums) {
int[] res = new int[2];
Set<Integer> set = new HashSet<>();
for (int num : nums) {
if (set.contains(num)) set.remove(num);
else set.add(num);
}
int i = 0;
for (int s : set) {
res[i++] = s;
}
return res;
}
}
时间复杂度:O(n)。
空间复杂度:O(n)。
3.相关知识
3.1 二进制表示
参考:
https://blog.csdn.net/weixin_43215250/article/details/84193451
5:
00000000 00000000 00000000 00000101
-5:
11111111 11111111 11111111 11111011
负数由反码加1构成