PythonTip中挑战题目

1、字符串逆序:

这个直接

print a[::-1]

2、求解100以内的所有素数

flag = [0]*100
flag[0]=1 
for i in range(2,100):
    for j in range(i*i,len(flag)+1,i):
        flag[j-1]=1
for k in range(len(flag)):
    if flag[k]==0:
        print k+1,

这个结尾最后会有空格,可以考虑join或者先都写到字符串中,如果数字大的话开销会非常大

另外,有个一行解法:

print ' '.join([str(d) for d in filter(lambda x: x>1 and all([x%c for c in range(2,x)]) or False, range(100))])

print ' '.join(map(str,reduce(lambda l,x:l if any([x%i==0 for i in l]) else l + [x],range(2,100),[])))

还有个两行解法,先对素数进行优化

import math
print " ".join([str(x) for x in range(2,100) if 0 not in [x%d for d in range(2,int(math.sqrt(x))+1)]])

但这个效率不高

3、0的个数:

就是简单的提取列表中每个元素中2和5的个数,返回最小值即可。这里注意其实可以优化,比如10的倍数,另外如果有0的话直接返回1

def zeroNum(L):
    num2=0
    num5=0
    zeronum = 0
    for i in range(len(L)):
        if L[i]!=0:
            while L[i]%2==0 or L[i]%5==0:
                if L[i]%2==0:
                    num2+=1
                    L[i]=L[i]/2
                if L[i]%5==0:
                    num5+=1
                    L[i]=L[i]/5
    else: print 1 print num2 print num5 print min(num2,num5) L=[2,5,7,8,55] zeroNum(L)

有个reduce版本:

result reduce(lamda x, y: x*y, L)

count = 0

while result % 10 == 0:

    count += 1

    result /= 10

print count

4、结尾非零数的奇偶性:

在上一题基础上,2多为偶,否则为奇

5、一个数2进制中1的个数:

对于一个2进制数如果数1的个数可以右移该数,对于10进制数来说,右移即/2

count = 0
while(a!=0):
    if a%2!=0:count+=1
    a = a/2
print count

6、大小写转换:

print a.lower()

 7、人民币转换:

def pt(a):
    alabo = '零壹贰叁肆伍陆柒捌玖'.decode('utf8')
    jinzhi = '拾佰仟'.decode('utf8')
    flag = ''
    if a<0:
        flag = ''.decode('utf8')
        a = abs(a)
    return flag+pstr(a, alabo, jinzhi)
def tolist(data):
    datalist = []
    datalist.append(data%10)
    data = data/10
    while data:
        datalist.append(data%10)
        data = data/10
    #print datalist[::-1]
    return datalist
def pstr(a, alabo, jinzhi):
    wstr = ''
    zeroflag = False
    high = a/10000;
    low = a%10000
    highlist = tolist(high)[::-1]
    LenHigh = len(highlist)
    for i in range(LenHigh):
        if highlist[i]==0:
            if not zeroflag:
                zeroflag = True
        else:
            if zeroflag:
                wstr += alabo[0]
                zeroflag = False
            wstr += alabo[highlist[i]]
            if i!=LenHigh-1:
                wstr += jinzhi[LenHigh-2-i]
    if wstr!='':
        wstr += ''.decode('utf8')
        
    lowlist = tolist(low)
    for k in range(4-len(lowlist)):
        lowlist.append(0)
    lowlist = lowlist[::-1]
    #print lowlist
    LenLow = len(lowlist)
    for j in range(LenLow):
        if lowlist[j]==0:
            if not zeroflag:
                zeroflag = True
        else:
            if zeroflag:
                if wstr != '':
                    wstr += alabo[0]
                zeroflag = False
            wstr += alabo[lowlist[j]]
            if j!=LenLow-1:
                wstr += jinzhi[LenLow-2-j]
    if wstr=='':
        return alabo[0]+(''.decode('utf8'))
    return wstr+(''.decode('utf8'))
print pt(a)

值得注意的就是编码,用u''或直接.decode()

8、公约数个数:

先辗转相除算出最大公约数,然后求最大公约数的约数个数,注意有1,感觉效率不是很高

def gcd(a,b):
    if a%b!=0: return gcd(b,a%b)
    else: return b

ans = gcd(100,80)
count = 2
for i in range(2,ans/2+1):
    if ans%i==0: count+=1
print count

有个两行的版本:

gcd = lambda x,y:gcd(y,x) if y < x else gcd(x,y%x) if y%x else x
print str(len([x for x in range(2,gcd(a,b)+1) if b%x==0 and a%x==0])+1)

9、逆求最大公约数和最小公倍数:

最小公倍数和最大公约数相除的倍数,对这个倍数开始找其中约数互质的那一对,最后找出和最小的

def gcd(a,b):
    if a%b!=0: return gcd(b,a%b)
    else: return b

a = input()
b = input()
times = b/a
flag = 0
c = 100000000000000
d = 100000000000000
if gcd(a,b)==1: print('none\n')
else:
    for i in range(2,times/2+1):
        if times%i==0:
            tmp = times/i
            if gcd(tmp,i)==1:
                flag =1
                if a*i+a*tmp<c+d:
                    c=a*i
                    d=a*tmp

    if 0==flag:
        print a,b
    else: print c,d

 10、LOVE

两点注意:1、对于love包含大小写共有2^4种字符串,不如反向直接将原字符串全部大写或者小写,然后再找

2、字符串的upper()和lower()函数是创建一个新的对象,或者说,还是python的设计原则,字符串是不可变的,即如果a.lower()后,a其实没有变,不能再在a里找

11、信息加密

没啥技巧,两行

s = "abcdefghijklmnopqrstuvwxyz"
print "".join(map(lambda c:s[(s.index(c)+b)%26], a))

 12、回文字串

先给出代码:

a = 'abdcdfga'
n = 4
flag = 0
for i in range(len(a)-n+1):
    tmp = a[i:i+n]
    print tmp
    if tmp in a:
        tmp1 = tmp[::-1]
        print tmp1
        if tmp1 == tmp:
            flag = 1
if flag: print 'YES'
else : print 'NO'

这里唯一要注意的是range范围,另外python如果切片操作过界后是只会减少切片长度,不会报错。比如a[6:6+4],这时会返回ga

13、一马当先

用优先队列实现BFS:

from collections import deque
def steps(n, m):
    dx = [-1, -2, -2, -1, +1, +2, +2, +1]
    dy = [+2, +1, -1, -2, -2, -1, +1, +2]
    v = {(x, y) : False for x in range(0,n+1) for y in range(0,m+1)}
    v[(0, 0)] = True
    q = deque([(0, 0, 0)])
    while len(q)>0:
        p = q.popleft()
        for i in range(0, 8):
            x = p[0] + dx[i]
            y = p[1] + dy[i]
            if x < 0 or x > n or y < 0 or y > m:
                continue
            if v[(x, y)]:
                continue
            v[(x, y)] = True
            q.append((x, y, p[2]+1))
            if x == n and y == m:
                return p[2]+1
    return -1
print steps(n, m)

 14、加油站

这个题还算不错,套了个背景将最大子序列和扩展了一下

L=[]
curIndex = 0
for i in range(len(cost)):
    L.append(limit[i]-cost[i])
maxNum = 0
tmp = 0
index = 0
if sum(L)<0:print -1
else:
    for i in range(len(L)):
        tmp = 0
        for j in range(len(L)):
            j+=i
            tmp +=L[j%len(L)]
            if tmp<0:
                tmp = 0
                curIndex = j+1
        
            if maxNum<tmp:
                maxNum = tmp
                index = curIndex
    print index

 15、快速幂取模

(转自好久前看的,忘了是谁写的了,貌似Alex转别人的)

在很多的时候,我们都要对三个整数a,b,c(b>=0,m>0)求(a^b)%m, 最朴素的想法是这样:
int pou(int a,int b,int m)
{
    int ret=1;
    a%=m;
    for(int i=0; i<b; ++i) ret=(ret*a)%m;
    return ret;
}

分析这个算法的性能,for循环一共要执行b次,当b很大的时候,算法的效率是很低的。
其实我们有更好的办法:
仔细想想我们可以发现:
1)当b是大于0的偶数时,我们有: a^b=a^(b/2)*a^(b/2);
2)当b是大于0的奇数时,我们有: a^b=a^(b/2)*a^(b/2)*a;

于是我们可以用下面的办法递归来求 (a^b)%m(由于我们可以先处理a%=m这一步,所以假设a<m,这样做是为了避免因为a太大而导致计算过程中溢出):

int pou(int a,int b,int m)
{
    if(!b) return 1;
    if(b==1) return a;
    int t=pou(a,b/2,m);
    if(b%2==1) return (((t*t)%m)*a)%m;
    return (t*t)%m;
}

分析这份代码的效率:
 设f(b)表示代码执行乘一个数再取模的次数;
 则:
 0) f(0)=0,f(1)=1;
 1) b是奇数时 f(b)=f(b/2)+2;
 2)   b是偶数时 f(b)=f(b/2)+1;
所以有:         
 f(b)<=f(b/2)+2; 
算法的运算次数是log(b) 级别的
而对于第一种方法,我们有
 f(b)=f(b/2)+b/2;
算法的运算次数是线性级别的。
对于b=2^n,第二个算法执行乘一个数再取模操作的次数为n次,而第一个为2^n次。
显然,第二个函数比第一个快多了呀快多了。

我们也可以把它写成迭代的形式,于是有下面的代码:

#define typec int    // or long long 
typec pou(typec a,int b,int m)
{
    typec t=a,ret=1;
    while(b)
    {
      if(b%2==1)  ret=(ret*t)%m;
      t=(t*t)%m;
      b/=2;
    }
    return ret;
}

 

posted @ 2014-04-10 21:31  逆光流觞  阅读(505)  评论(0)    收藏  举报