面试题56 - I. 数组中数字出现的次数
一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
示例 1:
输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]
示例 2:
输入:nums = [1,2,10,4,1,4,3,3]
输出:[2,10] 或 [10,2]
限制:
2 <= nums <= 10000
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
一种方法是使用 Set 保存已经存在的数,如果再次出现就把它从 Set 删除,留下只出现一次的数。
更好的方法是使用异或的思想。如果一个数字出现了两次,那么异或以后就是 0,最后剩下只出现一次的数的异或。
解答
方法一:
class Solution {
private Set<Integer> numSet = new HashSet<>();
public int[] singleNumbers(int[] nums) {
for (int n : nums) {
if (numSet.contains(n)) {
numSet.remove(n);
} else {
numSet.add(n);
}
}
int[] result = new int[2];
int i = 0;
for (int n : numSet) {
result[i++] = n;
if (i == 2) {
break;
}
}
return result;
}
}
方法二:
class Solution {
public int[] singleNumbers(int[] nums) {
int xor = 0;
for (int n : nums) {
xor ^= n;
}
int d = 1;
// 找出只出现一次的两个数 a、b 的不相同的最低位。
while ((d & xor) == 0) {
d <<= 1;
}
int a = 0;
int b = 0;
// 根据找到的最低位分组
for (int n : nums) {
if ((n & d) == 0) {
a ^= n;
} else {
b ^= n;
}
}
return new int[]{a, b};
}
}