题目的要求是:
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
示例 1:
输入: [2,2,1] 输出: 1
示例 2:
输入: [4,1,2,1,2] 输出: 4
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
分析
虽然可以借助键值对等数据结构(java中的map,python中的字典)来完成这题,但终究还是使用了额外的空间。
class Solution(object):
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
temp = {}
for i in range(len(nums)):
temp[nums[i]] = temp.get(nums[i], 0) + 1
for key in temp:
if temp[key] == 1:
return key
return -1
要做到在不使用额外的空间、且保证线性复杂度的情况下,完成这道题,只能用位运算中的异或了(^)
先来回顾一下位运算的基本判定方法
0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0
符合的运算定律
1、可交换
a ^ b = b ^ a
2、可结合
a ^ b ^ c = a ^ ( b ^ c )
3、与自身的运算一定为false(0)
a ^ a = 0
4、任何值与0异或,都等于这个数的本身
a ^ 0 = a
综合考虑上述的几个定律,这一题就不难了。
a ^ b ^ a ^ b ^ c ^ c ^ d ^ e ^ e
= a ^ a ^ b ^ b ^ c ^ c ^ e ^ e ^ d (定律1)
= ( a ^ a ) ^ ( b ^ b ) ^ ( c ^ c ) ^ ( e ^ e ) ^ d (定律2)
= 0 ^ 0 ^ 0 ^ 0 ^ d (定律3)
= 0 ^ d (定律4)
=d
只要将这个数组中所有的数做与或运算,就可以找到落单的那个
class Solution(object):
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
res = 0
for var in nums:
res ^= var
return res
异或在加密和备份等领域都有使用,感兴趣可以访问下面参考链接中的博客。
参考: http://www.ruanyifeng.com/blog/2021/01/_xor.html