Leetcode Algorithm No.260 Single Number III

本文介绍了一种线性时间复杂度的算法来找出数组中仅出现一次的两个元素,并提供了三种实现方式,包括简化版代码和进阶写法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

260 Single Number III

Givenan array of numbers nums, in which exactly two elements appear onlyonce and all the other elements appear exactly twice. Find the two elementsthat appear only once.

Forexample:

Given nums= [1, 2, 1, 3, 2, 5], return [3, 5].

Note:

  1. The order of the result is not important. So in the above example, [5, 3] is also correct.
  2. Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?

解决方法

nums = [1, 2, 1, 3, 2, 5]

def singleNumber(nums):

    ''' 对nums 中的所有值求异或结果,为两个唯一只出现了一次的数的异或值,其它出现两次的数的

    异或值都为0'''

    xor = nums[0]

    for i in nums[1:]:

        xor = xor^i

    '''xor = 6(0110) = 3^5'''

    ''' 求出 3 跟5 的第几位不相同。3(0011), 5(0101), 右数第一位上均为1,右数第二位不相同

    '''

    i = 1

    while xor:

        if xor/2 != xor>>1:

            break

        xor = xor>>1

        i+=1      

    ''' flag 为一个第i位为1,其它位为0的数'''

    flag = 2**(i-1)

    '''以第二位做判断将nums 中所有数分两组,第二位为0的一组,第二位为1的一组'''

    l1 = []

    l2 = []

    for i in nums:

        if flag&i == 0:

            l1.append(i)

        else:

            l2.append(i)

    xor = l1[0]

    for i in l1[1:]:

        xor = xor^i

    n1 = xor

    xor = l2[0]

    for i in l2[1:]:

        xor = xor^i

    n2 = xor

    return [n1,n2]

print(singleNumber(nums))

 

 

化简的代码

nums = [-1,0]

def singleNumber(nums):

    xor = nums[0]

    for i in nums[1:]:

        xor = xor^i

    i = 1

       

    flag = xor & (-xor)

    n1 = 0

    n2 = 0

    for i in nums:

        if flag&i == 0:

            n1 ^= i

        else:

            n2 ^= i

    return [n1,n2]

print(singleNumber(nums))

 

进阶的写法

http://www.codesec.net/view/184532.html

import functools

nums = [1, 2, 1, 3, 2, 5]

def singleNumber(nums):

    xor = functools.reduce(lambda x, y : x ^ y, nums)

    '''lowbit等于从低位向高位,第一个非0位所对应的数字'''

    ''' xor = 6(0110), -xor = -6(1011) 补码 '''

    lowbit = xor & -xor

    ''' lowbit = 2 '''

    a = b = 0

    for num in nums:

        if num & lowbit:

            a ^= num

        else:

            b ^= num

    return [a, b]

print(singleNumber(nums))

 

  1. reduce 的用法

functools.reduce(function, iterable[,initializer])

Apply function of two arguments cumulatively to the items of sequence,from left to right, so as to reduce the sequence to a single value.

使用前需要先导入functools 模块

>>> a=[1,2,3,4]

>>> import functools

>>> b=functools.reduce(lambda x,y:x+y, a)

>>> b

10

>>> b=a[0]+a[1]+a[2]+a[3]=1+2+3+4

 

  1. 关于补码

6 的原码 0110

-6 的原码 1110

-6 的补码 1001+1 = 1010, 符号位不变,其余位取反,再+1

-6 的补码的补码 1110 , 与原码相等

 

  1. 位与(&)

一个数n,

n & -n 的结果为从n的低位向高位,第一个非0位所对应的数字

例如n=3(0011), -n=(1101), n&-n = 0001 = 1

再如n=5(0101),-n=(1011),n&-n = 0001 = 1

说明3跟5的第一位是1

 

  1. 异或

相同的数异或为0,

0110 ^ 0110 = 0000

0与一个非0数异或等于这个非0数,

0000 ^ 0111 = 0111

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值