[算法][经典面试题]数组中只出现一次的数字|变体题目(一个不重复、二个不重复)

1. 原题

一个整型数组里除了一个数字之外,其他的数字都出现了两次。请写程序找出这一个只出现一次的数字。

解题思路:利用异或操作的性质可以快速解决这个问题。

异或运算法则

  1. a ^ 0 = a——与 0 0 0异或等于自身;
  2. a ^ a = 0——与自身异或等于 0 0 0
  3. a ^ b ^ c = a ^ c ^ b——交换律;
  4. a ^ b = c <=> a ^ c = b <=> b ^ c = a

代码如下,复杂度 O ( n ) O(n) O(n):

from functools import reduce
res = reduce(lambda x, y: x ^ y, array)
print(res)

2. 变体

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

变体难度与解决思路

由于这一次变成了需要找到两个思路,如果还按照原题进行异或操作,则两个不重复的数会进行异或叠加,需要将异或叠加的状态值拆解出来;根据异或运算法则4,则必须知道其中一个不重复数字才能拆解出另一个。

于是,考虑第一轮异或得到的结果res,其二进制表示中,取得1的位,不重复数字 a a a b b b在该位上比不相同(根据异或运算0^1=1得知);那么找到第一个不相同的位,根据是否与该位相同把原数列划分为两份,则分别包含 a a a b b b,再根据上一问中的解法进行求解即可,算法复杂度为 O ( 2 ∗ n ) O(2*n) O(2n)(可以进一步优化到 O ( 3 n 2 ) O(\frac{3n}{2}) O(23n))。

def find( array):
    res = reduce(lambda x, y: x ^ y, array)
    # 异或结果中为1的是不重复数字a和b不同的位
    index, res_store = 1, res  # index取第一个遇见的1,根据此位把array划分为两组再异或
    while res & 0b1 != 1:
        res, index = res >> 1, index << 1

    # 跟不重复数字a在index位上相同的数字列表
    a = reduce(lambda x, y: x ^ y, filter(lambda x: x & index, array))
    return a, a ^ res_store  # 根据 a^b=c <=> a^c=b
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值