题目
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
示例 2:
输入: [4,1,2,1,2]
输出: 4
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/single-number
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
-
题目要求不使用额外空间,官方解法为位运算,即数组中的全部元素的异或运算结果。
-
a⊕b = (¬a ∧ b) ∨ (a ∧¬b)
-
相异为 1 ,相同为 0
-
部分运算法则:
恒等律:a ⊕ 0 = a
自反:a ⊕ b ⊕ a = b
(当数组全部元素异或时同理)
-
-
如不考虑题目要求,想到的思路↓
- 使用哈希表,存储数组中每个数字和其出现的次数,遍历数组得到哈希表中的键值对,然后遍历哈希表,找到键值为1的键;
//运行效果:1400+ ms
class Solution:
def singleNumber(self, nums: List[int]) -> int:
dic = {}
for i in nums:
if i in dic:
del dic[i]
else:dic[i] = 1
for key in dic.keys():
return key
类似于第2点使用集合的思路,字典数据结构效果更优,可以方便的找到键,而列表需要有下标
- 使用集合,遍历数组,在集合中出现过的数字元素删除,最后留下的就是只出现一次的数字;
//运行效果:1400+ ms
class Solution:
def singleNumber(self, nums: List[int]) -> int:
a = []
for i in nums:
if i in a:
a.remove(i)//移除出现i值的第一个
else:a.append(i)
return a[0]
- 步骤较简单的是直接利用list.count()方法,遍历数组,运算每个数字的出现次数,判断得到出现次数为一次的返回值;
//运行效果:8000+ ms
class Solution:
def singleNumber(self, nums: List[int]) -> int:
for i in nums:
if nums.count(i) == 1:
return i
取巧
去重set()得到新数组nums1,利用数学方法,结合题意,nums中只有出现两次和一个出现一次的值。
2*sum(nums1) - sum(nums)
// set()去重
class Solution:
def singleNumber(self, nums: List[int]) -> int:
return 2*sum(set(nums)) - sum(nums)
代码
利用异或运算
// 异或
class Solution:
def singleNumber(self, nums: List[int]) -> int:
ret = 0
for i in nums:
ret ^= i
return ret
官方解
class Solution:
def singleNumber(self, nums: List[int]) -> int:
return reduce(lambda x, y: x ^ y, nums)
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/single-number/solution/zhi-chu-xian-yi-ci-de-shu-zi-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
总结
- 此题在解时并未想到异或运算,对运算方法的使用理解还不深入,关于涉及数组运算方面继续练习加强;
- 对字典、列表数据结构的使用更加熟悉。