题目描述:
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
示例 2:
输入: [4,1,2,1,2]
输出: 4
题解一、栈(利用了额外空间)
class Solution(object):
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
one_time = nums[0]
stack = [] # 栈
stack.append(nums[0])
for i in range(1, len(nums)):
if nums[i] in stack:
index = stack.index(nums[i])
a= stack.pop(index)
else:
stack.append(nums[i])
return stack[0]
这个方法的灵感来源于力扣刷题系列中的(三)
即引入一个列表,每次判断是否在里面,不在就加进去,在的话就直接删掉。
题解二、哈希表
我们用哈希表避免每次查找元素是否存在需要的 O(n)O(n) 时间。
- 遍历nums 中的每一个元素
- 查找hash_table 中是否有当前元素的键
- 如果没有,将当前元素作为键插入hash_table
- 最后, hash_table 中仅有一个元素,用 popitem 获得它
class Solution(object):
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
hash_table = {}
for i in nums:
try:
hash_table.pop(i)
except:
hash_table[i] = 1
return hash_table.popitem()[0]
函数介绍:
Python 字典 popitem() 方法随机返回并删除字典中的最后一对键和值。
如果字典已经为空,却调用了此方法,就报出KeyError异常。
这里就是用字典的键存储nums中的值,然后调用popitem函数删除最后一个元素(因为最后只有一个元素),得到一个元组。然后只取第一个元素(index=0)即可。
**优点:**拿异常处理代替了in的判断,进而缩短了时间复杂度
复杂度分析
时间复杂度: O(n \cdot 1) = O(n)O(n⋅1)=O(n) 。for 循环的时间复杂度是 O(n)O(n) 的。Python 中哈希表的 pop 操作时间复杂度为O(1)O(1) 。
空间复杂度: O(n)O(n) 。hash_tablehash_table 需要的空间与 \text{nums}nums 中元素个数相等。
题解三、位操作
class Solution:
def singleNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
a = 0
for num in nums:
a = a ^ num
return a