您的位置:首页 > 其它

LeetCode 260. Single Number III

2016-04-09 15:46 363 查看
原题网址: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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: