我用位运算找出只出现一次的数字

950 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

这是一道leetcode上的题目:只出现一次的数字

image.png

作为一个称职的菜鸟,第一眼看到的时候,第一反应当然是统计大法好。 用字典(哈希表)统计每个元素出现的次数,找出统计次数为1的元素返回,秒杀。 时间复杂度o(n),空间复杂度o(n)。

class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        cntdict ={}
        for n in nums:
            cntdict[n] = cntdict.get(n,0) +1
        for n,cnt in cntdict.items():
            if cnt == 1:
                return n

正当我洋洋得意,惊叹于自己的才华和反应速度时,并且准备洗洗睡了时,看到下面的题目要求:

不使用额外的空间

我擦了擦老花镜,怀疑是自己看错的时候,那句:

不使用额外的空间

仿佛在屏幕里裂开了嘴嘲笑我。

我扶了扶老花镜,抓了抓最近有些稀薄的头发,开始了头脑风暴:

在这里插入图片描述

不使用额外的空间? 排序?快速排序然后看邻近元素是否有重复? 快速排序时间复杂度O(nlogn),似乎不够优雅....

	def singleNumber(self, nums: List[int]) -> int:
		nums = sorted(nums)
		i = 0
		while(i<len(nums)-1):
			if nums[i] == nums[i+1]:
				i+=2
			else:
				return nums[i]
		if i == len(nums)-1:
			return nums[i]

我躺在床上,辗转反侧,开始思考怎样才能不掉发

在这里插入图片描述

不不不,是怎样才能在线性时间内不使用额外的空间找到只出现一次的元素。

我最终还是臣服于自己的智商,点开了题解

什么?异或运算? 两行代码就解决了?

异或运算介绍

异或(xor)是一个数学运算符。它应用于逻辑运算。异或的数学符号为“⊕”,计算机符号为“xor”。 二进制下异或运算法则: 1 xor 1=0 0 xor 0=0 1 xor 0=1 0 xor 1=1 因此十进制下相同数字异或结果为0,数字a与0异或结果仍为原来的数字a。 另外有:

  1. a ⊕ a = 0
  2. a ⊕ b = b ⊕ a
  3. a ⊕ b ⊕ c = a ⊕ (b ⊕ c) = (a ⊕ b) ⊕ c;
  4. a ⊕ b ⊕ a = b. 因此本题中异或全部的元素的结果就是那个只出现1次的元素。
	def singleNumber(self, nums: List[int]) -> int:
		sum = 0
		for n in nums:
			sum^=n
		return sum

我哭了 [表情包]

几个月后.... 恩?leetcode每日一题似乎挺熟悉? 好像有个牛逼的解法? 似乎可以用位运算? 哦...异或嘛,秒杀

我摸了摸自己的地中海,露出了欣慰的笑容。

在这里插入图片描述

送给大家我做的一个题解视频:

www.bilibili.com/video/BV16g…

点赞祭奠我逝去的头发