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
解法
位运算
每一位如果出现的次数刚好能整除3,那么多出来的那个数的这一位一定为0。
用one
和two
来记录每一位出现次数除以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] 最终结果 |
---|---|---|
0 | 0 | 0【不管是1^1 还是0^0 ,由于two[i]=0 ,最后结果都是0】 |
0 | 1 | 1 |
1 | 0 | 0【只可能是0^0 ,因为在运算前保证没有第四种情况】 |
1 | 1 | 0【只可能是0^1 ,此时转化成第1种情况】 |
综上可以得到:one[i] = ~two[i]&(one[i]^num[i])
接下来我们判断two[i]
什么时候为1,只有两种可能:
two[i]
原来就是1,one[i]
和num[i]
都是0two[i]
原来是0,one[i]
和num[i]
都是1
假如我们已经把one[i]
计算成新的了:
one[i]=1
的时候,two[i]
只可能是0one[i]=0
的时候,有以下几种可能:
two[i] | 原one[i] | num[i] | two[i] 最终结果 |
---|---|---|---|
0 | 0 | 0 | 0 |
0 | 1 | 1 | 1 |
1 | 0 | 0 | 1 |
1 | 0 | 1 | 0 |
由于原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