题目描述
给定一个整数数组 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 * 10^4
- -2^31 <= nums[i] <= 2^31 - 1
- 除两个只出现一次的整数外,nums 中的其他数字都出现两次
解答
思路一:
我们可以使用一个哈希映射统计数组中每一个元素出现的次数。
在统计完成后,我们对哈希映射进行遍历,将所有只出现了一次的数放入答案中。
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
unordered_map<int, int> freq;
for (int num: nums) {
++freq[num];
}
vector<int> ans;
for (const auto& [num, occ]: freq) {
if (occ == 1) {
ans.push_back(num);
}
}
return ans;
}
};
复杂度分析
- 时间复杂度:O(n)O(n),其中 nn 是数组 \textit{nums}nums 的长度。
- 空间复杂度:O(n)O(n),即为哈希映射需要使用的空间。
思路二(进阶):
位运算:
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
int xorsum = 0;
for (int num: nums) {
xorsum ^= num;
}
// 防止溢出
int lsb = (xorsum == INT_MIN ? xorsum : xorsum & (-xorsum));
int type1 = 0, type2 = 0;
for (int num: nums) {
if (num & lsb) {
type1 ^= num;
}
else {
type2 ^= num;
}
}
return {type1, type2};
}
};
复杂度分析
- 时间复杂度:O(n)O(n),其中 nn 是数组 \textit{nums}nums 的长度。
- 空间复杂度:O(1)O(1)。