dcddc

西米大人的博客

0%

落单的数 I II III

题目描述

落单的数I
给出2*n + 1 个的数字,除其中一个数字之外其他每个数字均出现两次,找到这个数字。

落单的数II
给出3*n + 1 个的数字,除其中一个数字之外其他每个数字均出现三次,找到这个数字。

落单的数III
给出2*n + 2个的数字,除其中两个数字之外其他每个数字均出现两次,找到这两个数字。

思路

落单的数系列题目因为是找落单的数,可以使用亦或。因为两个相同的数,亦或的结果为0
所以落单的数I 很容易就解决了

还可以把数组元素加入到hashmap,元素值作为key,元素出现的个数作为value,当value == 2时remove,最后遍历keyset把key输出即可
所以落单的数I II 很容易就解决了

落单的数III稍微复杂一点:

  • 亦或一遍,可以找到两个落单的数的亦或值
  • 找到这个值的二进制中第一个不为0的数的所在位,将该位为0的所有元素亦或一遍,该位所有为1的元素亦或一遍,就可以找到这两个落单的数

代码

1
2
3
4
5
6
7
8
9
10
public int singleNumber(int[] A) {
if(A.length == 0) {
return 0;
}
int n = A[0];
for(int i = 1; i < A.length; i++) {
n = n ^ A[i];
}
return n;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public int singleNumberII(int[] A) {
int res = 0;
HashMap<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < A.length; i++) {
if(map.containsKey(A[i])) {
map.put(A[i], map.get(A[i])+1);
if(map.get(A[i]) == 3) {
map.remove(A[i]);
}
}else {
map.put(A[i], 1);
}
}
for(Integer key : map.keySet()) {
res = key;
}
return res;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public List<Integer> singleNumberIII(int[] A) {
int res1 = A[0]; // 保存一遍亦或的结果
for(int i = 1; i < A.length; i++) {
res1 ^= A[i];
}

// 找到亦或的二进制数第一个不为0的数
int j = 1; // 第i位为1的值
while((res1 & j) == 0) {
j *= 2;
}
int res2 = 0; // 落单的数
int res3 = 0; // 落单的数
for(int num : A) {
if((num & j) == 0) {
res2 ^= num;
}else {
res3 ^= num;
}
}
List<Integer> list = new ArrayList<Integer>();
list.add(res2);
list.add(res3);
return list;
}

考察点

  • 位操作
  • HashMap