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?
解题思路:
1. 用HashSet ,速度慢。
2. 用Bit Manipulation。
首先计算nums数组中所有数字的异或,记为xor 令lowbit = xor & -xor,lowbit的含义为xor从低位向高位,第一个非0位所对应的数字 例如假设xor = 6(二进制:0110),则-xor为(二进制:1010,-6的补码,two's complement) 则lowbit = 2(二进制:0010)
根据异或运算的性质,“同0异1” 记只出现一次的两个数字分别为a与b,可知a & lowbit与b & lowbit的结果一定不同
通过这种方式,即可将a与b拆分开来。
Java code:
方法一:
public int[] singleNumber(int[] nums) { Set<Integer> set = new HashSet<Integer>(); int[] result = new int[2]; for(int i = 0; i< nums.length; i++){ if(set.contains(nums[i])){ set.remove(nums[i]); }else{ set.add(nums[i]); } } Iterator it = set.iterator(); result[0] = (int)it.next(); result[1] = (int)it.next(); return result; }
方法二:
public int[] singleNumber(int[] nums) { int record = 0; for(int num: nums){ record ^= num; } record &= -record; int[] result = {0, 0}; for(int num: nums){ if((num & record) == 0){ result[0] ^= num; }else{ result[1] ^= num; } } return result; }
Reference:
1. https://leetcode.com/discuss/52351/c-o-n-time-o-1-space-9-line-solution-with-detail-explanation
2. https://leetcode.com/discuss/52521/share-two-java-solution-%EF%BC%9Ad
3. http://bookshadow.com/weblog/2015/08/17/leetcode-single-number-iii/