要求
给定一个整数数组 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 中的其他数字都出现两次
核心代码
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
dic = collections.defaultdict(int)
for num in nums:
dic[num] += 1
return [key for key,val in dic.items() if val == 1]
另一解法
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
return [key for key,val in collections.Counter(nums).items() if val == 1]
第三种解法
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
a,b = 0,0
mask = 0
for num in nums:
mask ^= num
mask = mask & (-mask)
for num in nums:
if mask & num:
a ^= num
else:
b ^= num
return [a,b]
解题思路:第一种解法:我们使用空间换时间的方式,我们使用hash表存储出现次数,最终扫描所有的数据即可得到数据;第二种解法:是第一种解法的简化版本;第三种解法:首先要知道一个数和它本身 XOR的结果是 0;一个数和0 XOR 的结果是它本身。所以如果把整个数组的所有元素都XOR在一起,得到的结果= A ^ B ^ C ^ C ^ D ^ D(假设 A, B是只出现一次的元素, C, D是出现两次的元素) = A ^ B,因为A != B, 所以 A ^ B肯定不是0。令 mask = A ^ B, 然后采用一个特殊的运算:mask = mask & (-mask), 来找到mask不为0 的最后一位,在这一位上,A和B肯定不同,所以这一位才不是0,然后可以利用这个性质,把nums分成两个子数组,分别对应 & mask == 0 和 & mask == 1,然后问题变成了,两个相同的子问题:在一个数组里,只有一个元素出现了一次,其他元素都出现了两次,求这个元素的值
上面的思路是摘抄的,写下我自己的理解:A ^ B ^ C ^ C ^ D ^ D = A ^ B,因为是异或运算,假设A和B是相同的,结果一定是0,这样我们来寻找在二进制的最后某一位上为1的情况,a =10(1001),b = 7(0111) mask = a ^ b = (1101) mask = mask ^ (-mask) = 1;a =10(1001),b = 6(0110) mask = a ^ b = (1100) mask = mask ^ (-mask) = 4(100);所以我们的列表里面的值和mask与,结果(上面最后为1的那一位的结果)要么是零,要么是1,后面全是0,最终会分成两拨,a在一组里面,b在另一组里面,转化成在一个数组里,只有一个元素出现了一次,其他元素都出现了两次,求这个元素的值的问题。