难度中等358
给定一个整数数组 nums
,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。
进阶:你的算法应该具有线性时间复杂度。你能否仅使用常数空间复杂度来实现?
示例 1:
输入:nums = [1,2,1,3,2,5] 输出:[3,5] 解释:[5, 3] 也是有效的答案。
示例 2:
输入:nums = [-1,0] 输出:[-1,0]
示例 3:
输入:nums = [0,1] 输出:[1,0]
提示:
2 <= nums.length <= 3 * 104
-231 <= nums[i] <= 231 - 1
- 除两个只出现一次的整数外,
nums
中的其他数字都出现两次
显示详情
执行用时:1 ms, 在所有 Java 提交中击败了99.93%的用户
内存消耗:38.6 MB, 在所有 Java 提交中击败了73.25%的用户
class Solution {
public int[] singleNumber(int[] nums) {
int xorres=0;
int ans[]=new int[2];
for(int i=0;i<nums.length;i++){
xorres^=nums[i];
}
//xorres得到的是对数组所有数异或的结果
//结果就是两个不同元素的异或结果,根据异或原理,该数的二进制表示中,相同的位为0,不同为1.
//也就说分离出不同(二进制为1)的二进制位
//在xorres所有二进制位中,任意选一个1的位置
//遍历数字,该位置二进制为0的放到ans0,为1放到ans1
//这样做的思路是,两个相同的数在这个位置二进制位必然相同。
//我们就可以通过该二进制位将这个位置 “相同”二进制状态(0,1)的数分到一起异或从而约掉,
//“不同”二进制位的数刚好分到各自两个数里
int t=xorres;
int k=0;
while((t&1)==0){
t=t>>1;
k++;
}
int mask=(int)Math.pow(2,k);
for(int i=0;i<nums.length;i++){
if((nums[i]&mask)==0){
//该位置为0
ans[0]^=nums[i];
}else{
//该位置为1
ans[1]^=nums[i];
}
}
return ans;
}
}