Leetcode Algorithm No.260 Single Number III

来源:互联网 发布:淘宝买家具 编辑:程序博客网 时间:2024/06/05 03:39

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 ofsequence,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

 

0 0