260. Single Number III
- Total Accepted: 49443
- Total Submissions: 103739
- Difficulty: Medium
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?
给你一个数组,数组里只有两个数是出现一次的,其他数字都是出现两次,要求用O(n)时间复杂度,O(1)空间复杂度的算法找出这两个数
要是按以前我acm的做法,直接就是map存次数,又因为map自动有序,所以输出map[0]和map[1]就行了,but it can‘t let 空间复杂度保证O(1),
通过这题学到了一种巧妙的利用位运算解题的思路。
众所周知,x ^ x = 0,所以先用异或遍历一遍数组,设要输出的两个数一个为x,一个为y,那么遍历之后得到的结果为x^y,因为这x,y两个数不同,所以必定会
有起码有一位在各自的对应位上不同,又因为是异或,所以x^y中为1的位就是x和y中对应位不同的位置。设ans = x ^ y,利用ans&(-ans)求出最低为1
的位是哪一位,至于为什么
ans&(-ans)可以求出来,不会的可以去学一下树状数组(甩锅= =+),如果实在理解不了的,就用while循环求吧。求出这个最低位
之后,我们就可以根据数组中的元素在这一位是1还是0来把他们分为两组,这样就可以保证x,y被分开,然后对这两组分别进行异或求结果。这题是
Special judge,return 的数组中的元素不要求保证顺序。
public class Solution {
public int[] singleNumber(int[] nums) {
int ans = 0;
int a[] = new int [2];
int index = 1;
int len = nums.length;
for(int i=0;i<len;i++){
ans ^= nums[i];
}
index = ans & (-ans);
for(int i=0;i<len;i++){
if((nums[i] & index) == 0)
a[0] ^= nums[i];
else
a[1] ^= nums[i];
}
return a;
}
}