题目描述
一个整型数组里除了两个数字只出现一次,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
示例1
输入 [1,4,1,6]
返回值 [4,6]
说明:返回的结果中较小的数排在前面
解题方法
import java.util.Arrays;
import java.util.HashMap;
/**
* 一个整型数组里除了两个数字只出现一次,其他的数字都出现了两次。
* 请写程序找出这两个只出现一次的数字
* @author IT00ZYQ
* @date 2021/5/25 18:31
**/
public class 数组中只出现一次的两个数 {
/**
* 解法一:位运算
* 时间复杂度:O(n)
* 空间复杂度:O(1)
*/
public static int[] findSingleNumber1(int[] nums) {
// 遍历数组一次进行异或
// 遍历完数组后,xor为两个只出现一次的数异或的结果
int xor = 0;
for (int num : nums) {
xor ^= num;
}
// 最低位即最右边的1
int rightOne = xor & (~xor + 1);
int[] res = new int[2];
// 变量数组,找出两个只出现一次的数
for (int num : nums) {
if ((rightOne & num) == 0) {
res[0] ^= num;
} else {
res[1] ^= num;
}
}
// 排序,较小的数放前面
if (res[0] > res[1]) {
int t = res[0];
res[0] = res[1];
res[1] = t;
}
return res;
}
/**
* 解法二:哈希表
* 时间复杂度:O(n)
* 空间复杂度:O(1)
*/
public static int[] findSingleNumber2(int[] nums) {
HashMap<Integer, Integer> map = new HashMap<>();
// 遍历数组,统计数字出现的次数
// 最后剩余两个只出现一次的数
for (int num : nums) {
if (map.containsKey(num)) {
// 数字出现第二次时将其从map中移除
map.remove(num);
} else {
map.put(num, 1);
}
}
Integer[] res = new Integer[2];
map.keySet().toArray(res);
// 排序,较小的数放前面
if (res[0] > res[1]) {
int t = res[0];
res[0] = res[1];
res[1] = t;
}
return Arrays.stream(res).mapToInt(Integer::valueOf).toArray();
}
public static void main(String[] args) {
System.out.println(Arrays.toString(findSingleNumber1(new int[]{0, 1, 0, 3, 1, 5})));
System.out.println(Arrays.toString(findSingleNumber2(new int[]{0, 1, 0, 3, 1, 5})));
}
}