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:
[5, 3]
is also correct.
题目大意:一个整型数组中除了某两个数以外,其它的数都出现了两次,找出这两个数。
题目思路:
解法1:HashSet,遍历数组,把每个元素都放入hashset中,如果hashset中已经存在这个元素,则将这个元素移除,最后hashset中剩余的两个数就是要找的那两个数。代码如下:(10ms,beats 21.25%)
public int[] singleNumber(int[] nums) { Set<Integer> set = new HashSet<>(); int[] res = new int[2]; int index = 0; for (int num : nums) { if (!set.add(num)) set.remove(num); } Iterator<Integer> it = set.iterator(); while (it.hasNext()) res[index++] = it.next(); return res; }
解法二:题目要求只使用常数数量级的额外存储空间,则不使用解法1。可以使用位运算,计算数组中所有元素的异或值xor,由于数组中除了某两个数a、b,其他数都出现了两次,那么xor其实就为 a^b 。现在计算lowest = xor & (-xor),lowest的含义是从最低位开始取 xor 二进制表示中第一个‘1’所对应的值,假设xor = a^b = 12(即1100),则lowest = 4(即0100),那么说明在 从最低位开始 的第三位上,a和b对应的值一定不相同。那么a&lowest != b&lowest。那么解法就是:令a=b=0,对于数组中的每一个数num,如果num&lowest==0,则a^=num,否则b^=num。最后得到的a、b就是要求的那两个数。代码如下:(1ms,beats 78.47%)
public int[] singleNumber(int[] nums) { int[] res = new int[2]; int xor = 0, lowest, a = 0, b = 0; for (int num : nums) xor ^= num; lowest = xor & (-xor); for (int num : nums) { if ((num & lowest) == 0) a ^= num; else b ^= num; } res[0] = a; res[1] = b; return res; }