1. 输出间隔及末尾控制
设置标志flag
- 例如:要求输出参数之间以空格分隔,且末尾不能有空格
flag = False
==== 循环体 ====
print((" " if flag == True else “”) + “{}”.format(x), end="")
flag = True
=== 循环体结束 ===
- 在无限循环while循环体设置标志也非常有用,通过修改标志,可以建立循环体出口。
2. 判断素数
import math
def isPrime(n):
if n <= 1:
return False
for i in range(2, n):
if n % i == 0:
return False
return True
中阶版:
根据数学知识,在遍历判断时仅需判断至根号下n,可以减少一半的计算量。
import math
def isPrime(n):
if n <= 1:
return False
for i in range(2, int(math.sqrt(n)) + 1):
if n % i == 0:
return False
return True
高阶版:
除了2以外的所有偶数都不是素数,除了3以外能被3整除的都不是素数,以此类推。大大减少素数判断次数。
初始化标志列表,其中各个元素值都置为1。
将上述规律中不是素数的标志均置为0。
将处理过程分为两部分:
①修改标志列表中的值
②移动“指针”p至下一个素数
def prime(n):
flag = [1]*(n+2)
p=2
while(p<=n):
print(p)
for i in range(2*p,n+1,p):
flag[i] = 0
while 1:
p += 1
if(flag[p]==1):
break
运行结果:
>>> prime(20)
2
3
5
7
11
13
17
19
思考:为什么要构建大小为n+2的列表?
因为素数最小从2开始,为使序号匹配便于遍历flag,如上例中,要求小于等于20的素数,那么要保证flag[20]有效,根据切片性质,采用range方法,必须是range(:21)才能行得通。因此flag可遍历的序号应该是0-20,即flag大小是n+1。最终大小设置为n+2的原因是考虑到外层while循环退出,所以最后设置一个“哨兵”
3. 计算最大公约数
一、欧几里得算法(辗转相除法)
def gcd(a, b):
return (a if b == 0 else gcd(b, a % b))
在math模块中已经封装了gcd方法~
可以直接使用 math.gcd(a, b)
求最大公约数的思想源于2300多年前的欧几里得算法~
二、连续整数算法
取两数中较小值,递减判能否整除两数
4. 多条件排序
sorted()方法中的参数 key 可以附多个条件
格式:key=lambda <序列名> : (条件1,条件2, 条件3……)
>>> s1 = [['10000011', '85', '80'], ['10000003', '85', '80'], ['10000004', '80', '85'], ['10000013', '90', '99']]
>>> s2 = [['10000005', '82', '77'], ['10000006', '83', '76'], ['10000007', '90', '78']]
>>> s1 = sorted(s1, key=lambda s:(eval(s[1])+eval(s[2]), eval(s[1])), reverse=True)
>>> s2 = sorted(s2, key=lambda s:(eval(s[1])+eval(s[2]), eval(s[1])), reverse=True)
>>> s1
[['10000013', '90', '99'], ['10000011', '85', '80'], ['10000003', '85', '80'], ['10000004', '80', '85']]
>>> s2
[['10000007', '90', '78'], ['10000006', '83', '76'], ['10000005', '82', '77']]
5. 具有欺骗性的的round()
在仅保留一位小数时注意遵循整数部分“奇进偶弃”,其他情况正常
>>> round(10.5)
10
>>> round(11.5)
12
>>> round(12.5)
12
>>> round(10.55, 1)
10.6
>>> round(10.65, 1)
10.7
>>> round(11.55, 1)
11.6
可以使用decimal模块中的quantize()方法来解决~
>>> from decimal import Decimal
>>> x = Decimal('5.16')
>>> x.quantize(Decimal('0.0'))
Decimal('5.2')
>>> x = Decimal('5.14')
>>> x.quantize(Decimal('0.0'))
Decimal('5.1')
>>> x = Decimal('4.15')
>>> x.quantize(Decimal('0.0'))
Decimal('4.2')
6. 保留小数位边界情况的进位变号问题
可以参照B1051
7. 异常处理try-except-else
如果处理异常的except后对应多个异常情况,应采用括号的格式
try:
......
except (IndexError, TypeError, ...):
......
else:
......
8. 在编程考试中输入数据的处理
有时输入给出多组数据,并不一定要急于读入存储
可以逐个组读入并同时进行相应处理
相比全部读入再遍历处理显得较为明朗~
具体参见B1061
9.sorted()方法的妙用
10.正则表达式的应用
def func8():
import re
ls = eval(input())
lis = re.findall('[0-9]+', ls)
result = []
for num in lis:
if 3 <= len(num) <= 5:
result.append(int(num))
print(sorted(result, key=lambda x:sum(result)/x, reverse=False))
func8()
11.计算矩阵乘积和
第三方库numpy中的@矩阵乘法可以直接搞定。
那么如果不用第三方库呢?
matrix1 = eval(input())
matrix2 = eval(input())
matrix2R = [[row[i] for row in matrix2] for i in range(len(matrix2[0]))] #将第二个矩阵转置
result = []
for i in range(len(matrix1)): #用i控制遍历matrix1的列表元素
ls = [] #用于存储结果矩阵中的矩阵元素
temp = 0 #用于存储结果矩阵中矩阵元素中的值
for j in range(len(matrix2R)): #用j控制遍历matrix2R的列表元素
for k in range(len(matrix2R[0])): #用k遍历列表元素中的值
temp += matrix1[i][k]*matrix2R[j][k] #计算对应矩阵元素乘积和
ls.append(temp) #将结果添加到新的矩阵元素中
temp = 0
result.append(ls)
print(result)
示例:
==== RESTART ====
[[1,2,3,4]]
[[1],[2],[3],[4]]
result= [[30]]
>>>
==== RESTART ====
[[1,1,1],[2,2,2],[3,3,3]]
[[1,2,3],[1,2,3],[1,2,3]]
result= [[3, 6, 9], [6, 12, 18], [9, 18, 27]]
12.列表去重后排序(按原列表元素顺序)
name_lst = input().split(',') # 输入的字符串节分为列表
name_no_duplicate = list(set(name_lst)) # 去除重复的元素
print(sorted(name_no_duplicate, key=name_lst.index)) # 按名字在原列表中出现的顺序排序
输入
Calvin,bob,ada,McCord,Smith,Babbs,Calvin,Smith
输出
[‘Calvin’, ‘bob’, ‘ada’, ‘McCord’, ‘Smith’, ‘Babbs’]
13.分解质因数
什么是质因数?
n = eval(input())
ls = []
while n!=1:
for i in range(2, n+1):
if n%i == 0:
n //= i
ls.append(i)
break
或使用递归?
ls = []
def f(n):
for i in range(2, n+1):
if n%i == 0:
ls.append(i)
return f(n//i)
14.找完数
完数,即除本身以外,等于所有因子之和
m,n=map(int,input().split())
count=0
for i in range(m,n+1):
s=[k for k in range(1,i) if i%k==0] #这里因子不包括这个数本身
if sum(s)==i:
s.sort()
print("%d = %s"%(i," + ".join(map(str,s))))
count+=1
if count==0:
print("None")
如何解决超时?
如下:
m,n = map(int,input().split())
cnt = 0
for k in range(m,n+1):
factor = [1]
for i in range(2, int(k**0.5)+1):
if k%i == 0: #可以整除i,i是一个因子
factor.append(i)
if k//i not in factor: #除以i之后的商若不在因子列表中,则补充添加,这里区别于质因数分解,因此for语句的范围可以大大缩小
factor.append(k//i)
if sum(factor) == k:
factor.sort() #注意!!!为什么要重新排序?上述区分点的原因
cnt+=1
print(str(k)+" = "+" + ".join(map(str,factor)))
if cnt == 0:
print('None')