【Leetcode】137. Single Number II 只出现一次的数字 II

本文介绍了一种在数组中找到仅出现一次的元素的算法,该元素在其他元素都出现三次的情况下。算法使用位运算,确保线性时间和常数空间复杂度。详细解释了one和two变量如何记录每位出现次数的余数,并提供了Python代码实现。
摘要由CSDN通过智能技术生成

Given a non-empty array of integers, every element appears three times except for one, which appears exactly once. Find that single one.

Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

Example 1:

Input: [2,2,3,2]
Output: 3

Example 2:

Input: [0,1,0,1,0,1,99]
Output: 99

解法

参考评论区@TimeMac 的回复

位运算
每一位如果出现的次数刚好能整除3,那么多出来的那个数的这一位一定为0。
onetwo来记录每一位出现次数除以3的余数,即:

two[i],one[i] = 00,第i位出现3的整数倍次
two[i],one[i] = 01,第i位出现3的整数倍多一次
two[i],one[i] = 10,第i位出现3的整数倍多两次
two[i],one[i] = 11,第i位出现3的整数倍次,要去掉这种可能,把它转化为第一种情况

我们从头到尾把数组遍历一次,最后的每一位肯定要么出现3的整数倍次,要么出现3的整数倍多一次,也就是说最后one的取值就是我们的结果。
假设遍历到num
首先判断one[i]什么时候为1,什么时候为0,假如没有第4种情况,那么显然one[i] = one[i]^num[i]。考虑到第4种情况,我们可以列出下表:

two[i]one[i]^num[i]one[i]最终结果
000【不管是1^1还是0^0,由于two[i]=0,最后结果都是0】
011
100【只可能是0^0,因为在运算前保证没有第四种情况】
110【只可能是0^1,此时转化成第1种情况】

综上可以得到:one[i] = ~two[i]&(one[i]^num[i])
接下来我们判断two[i]什么时候为1,只有两种可能:

  1. two[i]原来就是1,one[i]num[i]都是0
  2. two[i]原来是0,one[i]num[i]都是1

假如我们已经把one[i]计算成新的了:

  1. one[i]=1的时候,two[i]只可能是0
  2. one[i]=0的时候,有以下几种可能:
two[i]one[i]num[i]two[i]最终结果
0000
0111
1001
1010

由于原one[i]已经不知道了,我们只能通过two[i]num[i]去求最终结果,分析真值表我们知道这肯定是一次异或操作:
two[i]^num[i]
所以有:two[i] = ~one[i]&(two[i]^num[i])
写成代码:

class Solution(object):
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        one = two = 0
        for n in nums:
            one = ~two & (one^n)
            two = ~one & (two^n)
        return one
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值