给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。 利用除答案以外的元素均出现两次,我们可以先对 nums 中的所有元素执行异或操作,得到 sum,sum 为两答案的异或值(sum 必然不为 0)。
然后取 sum 二进制表示中为 1 的任意一位 k,sumsum 中的第 k 位为 1 意味着两答案的第 k 位二进制表示不同。
对 nums 进行遍历,对第 k 位分别为 0 和 1 的元素分别求异或和(两答案必然会被分到不同的组),即为答案。
代码来源:宫水三叶力扣
class Solution {
public int[] singleNumber(int[] nums) {
int sum = 0;
for (int i : nums) sum ^= i;
int k = -1;
//i=31 因为最多是32
for (int i = 31; i >= 0 && k == -1; i--) {
if (((sum >> i) & 1) == 1) k = i; //if条件,用来确认当前位是否为1
//k用来保存从哪个位开始有1(即最高位有1 而当k!=-1时,此for循环会推出)
}
int[] ans = new int[2];
for (int i : nums) {
//对应之前的理论,此第k位,必定一个是0一个是1,否则不可能出现异或等于1 的情况
//而两个元素必然会分到不同的组中,只需要在两个组中分别求异或和即可
//而对于其他出现两次的干扰元素,因为是出现了两次,因此他们的异或和必然为0
if (((i >> k) & 1) == 1) ans[1] ^= i;
else ans[0] ^= i;
}
return ans;
}
}