标签:etc 出现 lang 不为 rem result 有一个 lin integer
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:
[5, 3]
is also correct.思路一:HashSet
顺序遍历数组,如果set中没有该数字,则放入该数字,如果有该数字,则移除该数字。遍历之后set中只剩下不重复的两个元素
public int[] singleNumber(int[] nums) {
Set<Integer> set = new HashSet<>();
for (int i = 0; i < nums.length; i++) {
if(set.contains(nums[i])) {
set.remove(nums[i]);
}else {
set.add(nums[i]);
}
}
int[] res = {0,0};
Iterator<Integer> iterator = set.iterator();
res[0] = (Integer)iterator.next();
res[1] = (Integer)iterator.next();
return res;
}
思路二:位操作
XOR:异或,当位不同的时候为1,相同的时候为0。如果两个数异或之后不为0,说明两个数不同。两个数异或的结果上如果有一位是1,则这个1一定来自于这两个数中的一个。
有一串二进制数为X,X&(-X) 的结果是 X 最右边的 1 的位置。详细见https://www.cnblogs.com/yzxag/p/12668034.html
求解思路:如果我们可以把数组内的元素进行分类,一类里面包含一个不同的元素和若干对相同的元素,另一类里面有另一个不同的元素和若干对相同的元素。这样,我们分别对两类元素相异或,得到的结果就是两个只出现了一次的元素。
下面对数组内的元素进行分类:
tmp & (-tmp)
选出一个 1,再次遍历数组,如果该位置上为 1 分入类别一,否则分为类别二。对两个类别中的元素进行异或,得到两个单独的数字。public int[] singleNumber(int[] nums) {
int tmp = 0;
for (int num : nums) // 得到所有数字异或的结果
tmp ^= num;
int dif = tmp & (-tmp); // 选取出最右边的一个 1
int[] res = new int[2];
for (int num : nums) // 再次遍历,如果该位置上为 1,则进行异或,得到其中一个数字
if ((num & dif) != 0)
res[0] ^= num;
res[1] = tmp ^ res[0]; // tmp 为两个不同元素的异或结果,即 tmp = res[0]^res[1],
return res; // res[1] = res[0]^res[1]^res[0]
}
标签:etc 出现 lang 不为 rem result 有一个 lin integer
原文地址:https://www.cnblogs.com/cdbb/p/13301823.html