目录
题目
给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。
进阶:你的算法应该具有线性时间复杂度。你能否仅使用常数空间复杂度来实现?
来源:力扣(LeetCode)
链接:原文链接
思路和代码
方法一:去重循环遍历统计次数
首先将数组用set()函数去重,根据原数组进行统计,将去重后得到的列表中出现2次的数字删除,直到去重后的列表长度为2。
注:复杂度不符合要求,需进一步优化
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
i,j,ans = 0,0,0
singlenum = list(set(nums))
while len(singlenum) is not 2:
for j in range(len(nums)):
if nums[j] == singlenum[i]:
ans += 1
if ans == 2:
del(singlenum[i])
else:
i += 1
ans = 0
return singlenum
方法二:哈希映射
用哈希映射统计数组中每一个元素出现的次数,再对哈希映射进行遍历,只出现了一次的数放入答案中即可。
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
numsfreq = Counter(nums)
return [num for num, occ in numsfreq.items() if occ == 1]
方法三:位运算
由a^a=0,0^b=b,推出,a^a^b=b。
由于题目所给数组中只有两个不同的数字出现一次,其他数字均出现两次,如果将整个数组进行异或运算,可得到a^b=c的结果。
而,c&(-c)可以得到c的二进制表示中为“1”的最低位,用lsb表示。若将整个数组与lsb进行与运算可以将整个数组分为两类,二进制表示中第lsb位是否为1,并且a与b不在同一类中。再分别将这两类中的数字进行异或运算,由于只有a,b只出现一次,因此异或后的结果就分别为a和b。
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
xorsum = 0
for num in nums:
xorsum ^= num
lsb = xorsum & (-xorsum)
print("lsb=",lsb)
type1 = type2 = 0
for num in nums:
if num & lsb:
type1 ^= num
else:
type2 ^= num
return [type1, type2]