力扣打卡:剑指 Offer 56 - I. 数组中数字出现的次数
解题思路
首先遍历一遍数组后,得到的是xor,也就是两个元素的异或结果
此时对xor取值,在xor的二进制中,数值为1的位置都是 a 和 b 的不同位置形成的,(相同为0,不同为1)
那么通过这个来区分数组中的元素,因为数组中的每一个元素要么在这个位置上为1,要么在这个位置上为0,所以分为两类
但是数组中的元素不对结果造成任何影响,因为数组中的元素都是出现了偶数次,异或的结果会将其抵消了
最终所剩下的结果就是两个出现一次的结果
代码
class Solution {
public int[] singleNumbersA(int[] nums) {
// 使用HashMap进行统计
HashMap<Integer,Integer> map = new HashMap<>();
for(int i: nums){
map.put(i,map.getOrDefault(i,0)+1);
}
int[] ans = new int[2];
int i = 0;
for(Map.Entry<Integer,Integer> entry : map.entrySet()){
if(entry.getValue()==1) ans[i++] = entry.getKey();
}
return ans;
}
// 重点理解异或位运算
public int[] singleNumbers(int[] nums) {
int xor = 0;
for(int i: nums){
xor ^= i;
}
int[] ans = new int[2];
// 此时的 xor 为 两个出现一次的元素的异或结果
int diff = xor & (~xor+1);// 按位取反后,再进行加1,此时能够取出最后一个1到末尾的二进制串
for(int i: nums){
if((i&diff)==0) ans[0]^=i;
else ans[1] ^= i;
}
return ans;
}
}