python练习

题目1:一个正整数数组,有2个数只出现了一次,其他的数都出现了2次,求出这2个只出现了一次的数。要求算法复杂度为O(n),空间复杂度为O(1)

思路:所有数相异或,出现2次的数消掉了,剩下的是出现1次的2个数相异或的结果,结果的为1的位表示这2个数的差异位。

比如list_t=[1,2,3,8,4,4,3,1,5,5],所有数相与的结果为‘0b1010’,2与8在第二位和第4位是不相同的。

将数组分成2部分,所有第4位为1的为一组,为0的在另一组。那么那2个只出现一次的数必然分开在了2边,而且相同的2个数也必然在同一边。

那么每一边都只会出现一个单独的数,对两边分别求异或,就可以得出单独的数。

#一个数组,有2个数只出现了一次,其他数都出现了2次,求出这2个数
import math

def findone(list_t,first_num,second_num):
    r=list_t[0]
    for i in list_t[1:len(list_t)]:    #这样求出了只出现一次的2个数之间的差异
        r=r^i
    #接下来要找到这2个数其中一个差异位
    str_r=bin(r)[2:len(bin(r))]      #把r转换为二进制形式。bin()将十进制整数转换为二进制字符串,前面有0b.
    r=int(math.pow(2,len(str_r)-1))
    m=0                              #用于分成两类的指针
    n=len(list_t)-1                                           
    while(m<n):                      #把数组中的数分成2类。一类是所有的数在位b上为1,另一类是不为1.这两个不同的数一定分开在这两边了                  
        while(list_t[n]&r!=0):
            n=n-1
        temp=list_t[n]               #第一个b位为1的数,存储在temp中
        while(m<n and list_t[m]&r==0):
            m=m+1
        list_t[n]=list_t[m]          #第一个b为不为1的数,移到前面,把temp中的数移到后面
        list_t[m]=temp
    print m                           #m表示的是最后一个b位不为1的数
    print list_t
    first=list_t[0]                    
    second=list_t[m+1]
    for i in list_t[1:m+1]:              #两个相同的数一定会在同一边,只分别出现一次的数一定分开在了两边。对这两边分别相与,可以得出出现一次的数
        first^=i
    for i in list_t[m+2:len(list_t)]:
        second^=i
    return first,second
       
first_num=0
second_num=0
list_t=[1,2,3,8,4,4,3,1,5,5,8,7]
first_num,second_num=findone(list_t,first_num,second_num)   #注意python可以一次返回多个值,多次赋值。python中的引用概念不强
print "first_num:%d" %first_num
print "second_num:%d" %second_num

#for i in range(1,len(str_r)):  #提取r的首位为1,其他为0。表示这两个数在某一个位b上不相同
        #str_r[i]='0'     #字符串不支持按位幅值
    #r=int(str_r,2)
        
        

几个注意的python语法:

1.bin(x) 将整数转换为二进制字符串,前面有0b字符,要去掉
2.math.pow(x,y)求x的y次幂
3.for i in range(1,len(str_r)): 注意range的写法
4.字符串不支持按位幅值
5.注意python可以一次返回多个值,调用时可采用多参数赋值。python中的引用概念不强
posted @ 2015-08-25 14:42  wy1290939507  阅读(183)  评论(0编辑  收藏  举报