1、题目
给你一个数组 nums ,数组中的数字 要么 出现一次,要么 出现两次。
请你返回数组中所有出现两次数字的按位 XOR 值,如果没有数字出现过两次,返回 0 。
示例 1:
输入:nums = [1,2,1,3]
输出:1
解释:
nums 中唯一出现过两次的数字是 1 。
示例 2:
输入:nums = [1,2,3]
输出:0
解释:
nums 中没有数字出现两次。
示例 3:
输入:nums = [1,2,2,1]
输出:3
解释:
数字 1 和 2 出现过两次。1 XOR 2 == 3 。
提示:
1 <= nums.length <= 50
1 <= nums[i] <= 50
nums 中每个数字要么出现过一次,要么出现过两次。
2、解
笨方法:统计每个数字出现次数;再将出现2次的数字进行XOR计算得到结果
int duplicateNumbersXOR(vector<int> &nums)
{
int result = 0;
unordered_map<int, int> numTimes;
for(int &num : nums){
numTimes[num]++;
}
for(auto &[num, time] : numTimes)
{
if(2 == time)
{
result = result ^ num;
}
}
return result;
}
进阶
优化版:题目有说1 <= nums[i] <= 50,就可以通过数组索引来表示数字,对应存储的数字表示出现次数节省空间。
int duplicateNumbersXORA(vector<int> &nums)
{
int result = 0;
int temp[52] = {0};
for(int &num : nums){
temp[num]++;
}
for(int i = 0; i < 52; i++)
{
if(2 == temp[i])
{
result ^= i;
}
}
return result;
}
更优解题思路:位运算。(待仔细学习版)
int duplicateNumbersXORB(vector<int> &nums)
{
int ans = 0;
long long vis = 0;
for (int x : nums) {
if (vis >> x & 1) {
ans ^= x;
} else {
vis |= 1LL << x;
}
}
return ans;
}