原题网址:https://leetcode.com/problems/single-number-iii/
Given an array of numbers nums
, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.
For example:
Given nums = [1, 2, 1, 3, 2, 5]
, return [3, 5]
.
Note:
- The order of the result is not important. So in the above example,
[5, 3]
is also correct. - Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?
方法一:使用Map对数字进行计数,时间复杂度O(n),空间复杂度O(n)。
public class Solution {
public int[] singleNumber(int[] nums) {
Map<Integer, Integer> map = new HashMap<>();
for(int num: nums) {
if (map.containsKey(num)) map.remove(num); else map.put(num, 1);
}
int[] singles = new int[2];
int i=0;
for(Integer key: map.keySet()) singles[i++] = key;
return singles;
}
}
方法二:使用哈希集合。
public class Solution {
public int[] singleNumber(int[] nums) {
Set<Integer> set =new HashSet<>();
for(int num: nums) {
if (!set.add(num)) set.remove(num);
}
int[] singles = new int[2];
int i = 0;
for(int num: set) singles[i++] = num;
return singles;
}
}
public class Solution {
public int[] singleNumber(int[] nums) {
int[] singles = new int[2];
int zeros = 0;
for(int num: nums) if (num == 0) zeros ++;
if (zeros == 1) {
for(int num: nums) singles[1] ^= num;
} else {
for(long i=0, m=1; i<32; i++, m<<=1) {
int a=0, b=0;
for(int num: nums) {
if ((num & m) == 0) a ^= num; else b ^= num;
}
singles[0] = a;
singles[1] = b;
if (a != 0 && b != 0) break;
}
}
return singles;
}
}
方法四:在方法三的基础上,直接找出一个能够区分的比特。找出一个不同的比特,按这个比特来分组(HASH)。时间复杂度O(n),空间复杂度O(1)。
思路:两个数不同,则至少有一个比特不同,通过全部数字异或,则异或结果中的这个比特必为1。然后将全部数字根据这个不同的比特分为两组,各自再求一遍异或。
public class Solution {
public int[] singleNumber(int[] nums) {
//全部数字异或,必有至少一个比特位等于1
int xor = 0;
for(int num: nums) xor ^= num;
//找出这个异或结果为1的比特位
int bit = 1;
for(int i=0; i<31; i++, bit<<=1) {
if ((xor & bit) != 0) break;
}
// 根据这个比特位对nums分组,重新求异或
int xor0 = 0, xor1 = 0;
for(int num: nums) {
if ((num & bit) == 0) xor0 ^= num; else xor1 ^= num;
}
// 两个只出现一次的数字必定分在两个分组内
int[] singles = new int[2];
singles[0] = xor0;
singles[1] = xor1;
return singles;
}
}
参考: http://www.neozone.me/leetcode260.html