【经典题目】只出现x次的数字——异或操作

只出现x次的数字–巧用异或

入门级:只出现一次,其余数字出现了偶数次

在这里插入图片描述
很简单了,直接利用异或的性质,每次将数组所有数字的异或在一起,因为其他数字都出现了偶数次,所以异或结果就是唯一的奇数次的。

class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        ans = 0
        for i in nums:
            ans ^= i
        return ans

升级版:两个元素出现1次,其余出现两次

在这里插入图片描述
如果数组中有两个数字,问题就变的复杂了起来。因为难以区分两个数字。但是如果我们还是利用异或的性质的话还是可以发现一些端倪的。我们将整个数组异或起来,最后的结果肯定是两个数单独数字的异或和。因此我们可以分析这个二进制的数字,如果某一位是1说明两个数字在该位分别是0和1。因此我们可以利用这个特点对两个数字进行区分。

class Solution:
    def singleNumber(self, nums: List[int]) -> List[int]:
        cur = 0
        for i in nums:
            cur ^= i
        h = cur&(-cur)  # 找出cur的最后一个1, h=00000010000
        a = 0
        b = 0
        for i in nums:
            if h&i == 0:
                a ^= i
            else:
                b ^= i
        return [a, b]

最终版:其余元素出现了三次

在这里插入图片描述

这个就比较麻烦了,需要借助状态转移的方法,因为我们要转换为3进制。保证每次计数时候,从00-->01-->10-->00因此我们借助one和two两个。进行考虑。
参考题解

class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        one = 0
        two = 0
        for i in nums:
            one,two = (one^i)&(~two), ((~one)&(two&~i))|(one&i)
        return one
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值