leetcode [260]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.
Example:
Input:[1,2,1,3,2,5]
Output:[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?
题目大意:
一个数组中,只有两个数字只出现了一次,其他数字都出现了两次,找出这两个数字。
解法:
首先,把数组中的所有数字都异或得到一个结果,这个结果一定是两个只出现了一次的两个数字进行异或得到的结果,那么可以通过这个结果知道这两个数字在哪一位上是不同的,通过这一位将数组分为两个数组,那么这两个数组一定是每一个数组包含一个出现了一次的数字,而且数组剩下的数字都是成对出现的。将这两个数组分别进行异或,那么最后两个数组异或得到的数字就是结果。
java:
class Solution { public int[] singleNumber(int[] nums) { int[] res=new int[2]; int s=nums[0]; for (int i=1;i<nums.length;i++) s^=nums[i]; int flag=1; for(int i=0;i<32;i++){ if ((s&flag)!=0) break; flag<<=1; } ArrayList<Integer>l1=new ArrayList<>(); ArrayList<Integer>l2=new ArrayList<>(); for (int i=0;i<nums.length;i++){ if ((nums[i]&flag)!=0) l1.add(nums[i]); else l2.add(nums[i]); } s=l1.get(0); for (int i=1;i<l1.size();i++) s^=l1.get(i); res[0]=s; s=l2.get(0); for (int i=1;i<l2.size();i++) s^=l2.get(i); res[1]=s; return res; } }
优化过后的java:
s&=-s可以保留二进制中第一位为1,其余位置都补上0。比如6(二进制110)可以得到2(二进制10)。
class Solution { public int[] singleNumber(int[] nums) { int[] res=new int[2]; int s=nums[0]; for (int i=1;i<nums.length;i++) s^=nums[i]; s&=-s; for (int num:nums){ if ((num&s)==0) res[0]^=num; else res[1]^=num; } return res; } }