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;
}

浙公网安备 33010602011771号