LeetCode-260. 只出现一次的数字 III【位运算 数组,字节】
题目描述:
给你一个整数数组 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 中的其他数字都出现两次
解题思路一:全数组异或找到最低为1的比特位。必然有一个单个数字为1一个为0,分组异或之后变为:LeetCode-136. 只出现一次的数字【哈希表,位运算,排序,暴力】
代码实现时,需要找到异或和中的某个值为 1 的比特位。
一种方式是计算 lowbit,只保留二进制最低位的 1,举例如下:
s = 101100
~s = 010011
(~s)+1 = 010100 // 根据补码的定义,这就是 -s 效果:s 的最低 1 左侧取反,右侧不变
s & -s = 000100 // lowbit
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
xor_all = reduce(xor, nums)
lowbit = xor_all & -xor_all
ans = [0, 0]
for x in nums:
ans[(x & lowbit) != 0] ^= x # 分组异或
return ans
时间复杂度:O(n)
空间复杂度:O(1)
解题思路二:通俗版
class Solution:
def singleNumber(self, nums: List[int]) -> List[int]:
xor_all = 0 # 特性是x ^ 0 = x; x ^ 1 = -x
for x in nums:
xor_all ^= x
lowbit = xor_all & -xor_all # 补码和负数的补码且运算可以得到最低为1 的比特位
print(lowbit)
a = 0
b = 0
for x in nums:
if (x & lowbit) != lowbit: # 注意这里必须是 != 0 或者 != lowbit
a ^= x
else:
b ^= x
return [a, b]
时间复杂度:O(n)
空间复杂度:O(1)
解题思路三:0
时间复杂度:O(n)
空间复杂度:O(n)

♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠ ⊕ ♠