260. 只出现一次的数字 III
「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战」
给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。
进阶: 你的算法应该具有线性时间复杂度。你能否仅使用常数空间复杂度来实现?
示例 1:
输入: nums = [1,2,1,3,2,5]
输出: [3,5]
解释: [5, 3] 也是有效的答案。
示例 2:
输入: nums = [-1,0]
输出: [-1,0]
示例 3:
输入: nums = [0,1]
输出: [1,0]
提示:
2 <= nums.length <= 3 * 104-231 <= nums[i] <= 231 - 1- 除两个只出现一次的整数外,
nums中的其他数字都出现两次
解题思路
哈希表
- 用哈希表
unordered_set存储表内从未有过的数字 - 遍历数组,若哈希表内有此数字
num,则在哈希表内删除num,否则将num写入哈希表 - 返回最终剩余的哈希表内的数字
代码
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
unordered_set<int> ansSet;
for(auto &x:nums){
if(ansSet.find(x)!=ansSet.end()){//判断数字是否重复
ansSet.erase(x);//重复则删除
}else {
ansSet.insert(x);//不重复写入
}
}
return {ansSet.begin(),ansSet.end()};
}
};
位运算
前导知识:两个相同的数异或是零,多个数异或只要出现两个数相同,则异或结果就是把这两个数去掉剩下的数异或,即1^2^3^4^5^6^1^2==3^4^5^6
- 把数组内每一个数字
num异或得到两个仅出现一次的数字的异或值TwoNumsXor - 这两个数字至少有一位是不同的,并且其中一个
ansNum1该位为0(1),另一位ansNum2该位为1(0) - 找出最低位不同的方法是
TwoNumsXor&-TwoNumsXor,-TwoNumsXor为TwoNumsXor取反加1,二者异或肯定会得到一位且仅剩这位数字为1,说明TwoNumsXor本身该位就是1,1由0^1得来,说明了第2条的观点 - 每个数
num分别与Classification进行与操作即可分类,出现两次的数字肯定会分到一组,用结果ansNum异或此时的num最终即可得到该数字
代码
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
int TwoNumsXor=0;
for(auto &num:nums){
TwoNumsXor^=num;
}
int Classification=TwoNumsXor==INT_MIN?TwoNumsXor:TwoNumsXor&-TwoNumsXor;
int ansNum1=0;
int ansNum2=0;
for(auto &num:nums){
if(num&Classification){
ansNum1^=num;
}else {
ansNum2^=num;
}
}
return {ansNum1,ansNum2};
}
};
😝最近新创建了个开源仓库,总结LeetCode的每日一题,目前已有C++、JavaScript和部分Java、Python语言版本,欢迎大家完善补充! 🖥️仓库地址:每日一题系列