标签: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