前言:今年4月第一次参加蓝桥杯比赛,选择的Python 研究生组赛道。在备赛过程中,发现经常会用到一些编程小技巧,因此笔者整理了一些蓝桥杯Python组编程基础常用的内容,以便日后备用。如果有小伙伴也觉得实用,赶快点赞收藏一下~!(持续更新)
一、输入
单个数输入,一般不用eval函数,速度会比较慢。
# 整型输入
n = int(input())
# 浮点输入
k = float(input())
# 输入三个数,例如:1 2 3,除非有特殊字符截取,否则最好split()函数参数为空。
a,b,c = map(int,input().split())
# 输入一串数字,例如:1 2 3 4 5,得到列表[1,2,3,4,5]
s = list(map(int,input().split()))
二、输出
输出使用格式化符号比较习惯。
# 隔空输出
a = [1,2,3,4]
print(' '.join(map(str,a))) #1 2 3 4
# 四舍五入
a = 3.1415926
print(int(a + 0.5))
# 保留两位,仅截取两位小数,并不会四舍五入
a = 3.1415926
print("%.2f"%a)
# 保留两位+四舍五入。保留几位就在后一位上+5
print('%.2f'%(a+0.005)))
# 不足几位,前导/补0,'%03d'中间数字对应几位
print('%03d'%2) # '002'
三、声明创建列表
# 1.创建全0列表,长度为n的一维0列表
a = [0 for _ in range(n)]
# 或者
a = [0]*n
# [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# 2.创建二维空列表
a = [[] for _ in range(n)]
# [[], [], [], [], [], [], [], [], [], []]
# 3.创建二维全0列表,m行n列的0二维数组
a = [[0 for _ in range(n)] for _ in range(m)]
# 或者
a = [[0] * n for _ in range(m)]
# 注意:不能使用[[0]*n]*m,此语句m行将指向同一对象[0]*n,即引用的同一对象,改变一行其它行都会跟着变。
四、简单排序
4.1 列表函数sort()
list.sort(key=None,reverse=False),对原列表进行排序,如果指定参数,则使用比较函数指定的比较函数。
参数:
- key – 用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
- reverse – 排序规则,reverse = True 降序, reverse = False 升序(默认)。
注意:因为python中无法修改字符串元素,所以对字符串无法使用sort函数,必须先把字符串转换转换成列表list(str)。
list=[30,40,10,50,50.1,80,60,100,90]
list.sort() # 升序
# [10, 30, 40, 50, 50.1, 60, 80, 90, 100]
list.sort(reverse=True) # 降序
# [100, 90, 80, 60, 50.1, 50, 40, 30, 10]
aList = ['Google', 'Runoob', 'Taobao', 'Facebook']
aList.sort()
# ['Facebook', 'Google', 'Runoob', 'Taobao']
vowels = ['e', 'a', 'u', 'o', 'i']
# 降序
vowels.sort(reverse=True)
# ['u', 'o', 'i', 'e', 'a']
4.2 内置函数sorted()
sorted() 函数对所有可迭代的对象进行排序操作。
sort 与 sorted 区别:
sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。即对字符串也可以,因为sorted返回的是新对象。
list 的 sort 方法返回的是对已经存在的列表进行操作,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。
sorted(iterable, key=None, reverse=False),返回重新排序的新列表。
参数:
- iterable – 可迭代对象。
- key – 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
- reverse – 排序规则,reverse = True 降序 , reverse = False 升序(默认)。
sorted([5,2,3,1,4]) # 默认升序
# [1,2,3,4,5]
# sorted 的应用,也可以通过 key 的值来进行数组/字典的排序,比如:
# 获取列表中字典中key-age的值
def takeSecond(elem):
return elem['age']
array = [{"age":20,"name":"a"},{"age":25,"name":"b"},{"age":10,"name":"c"}]
array = sorted(array,key=takeSecond)
# [{'age': 10, 'name': 'c'}, {'age': 20, 'name': 'a'}, {'age': 25, 'name': 'b'}]
4.3 sort()与sorted()区别
- sort是应用在list上的方法,sorted可以对所有可迭代的对象进行排序操作;
- sort是在原列表上排序,而sorted产生一个新的列表,不改变原列表;
- 部分排序。sort()不能在一部分上做排序,只能整体排序。sorted()可以部分排序,但是不能在原数据上排序。
4.4 自定义比较函数 多列排序
- 自定义比较函数sort(key=f_sort)
- key – 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
# 自定义比较函数
def f_sort(elem): # 具体的函数的参数就是取自于可迭代对象中,即列表元素
return (b[elem],elem) # 返回用来比较的元素,若b[elem]相同,则比较elem,依次类推
例题1:
'''
题解:模拟排序题。
1.自定义比较函数sort(key=f_sort)
'''
# 输入
n = int(input())
m = int(input())
# 原数组
a = [i for i in range(1,n+1)]
# 数位和数组
b = [0]*(n+1)
for i in range(1,n+1):
# 求i的数位之和
num = i
while num != 0:
b[i] += num%10
num //= 10
# 自定义比较函数
def f_sort(elem): # 具体的函数的参数就是取自于可迭代对象中,即列表元素
return (b[elem],elem) # 返回用来比较的元素,若b[elem]相同,则比较elem,依次类推
# 排序
# a.sort(key=lambda x:(b[x],x))
a.sort(key=f_sort)
print(a)
print(a[m-1])
例题2:
'''
题解:模拟排序题。
1.自定义比较函数sort(key=f_sort)
2.多列排序,按总分高到低降序排列,总分相同的按语文成绩高到低降序排列,总分和语文都相同,按学号小升序排列。
例如:先按照成绩降序排序,相同成绩的按照名字升序排序:
d1 = [{'name':'alice', 'score':38}, {'name':'bob', 'score':18}, {'name':'darl', 'score':28}, {'name':'christ', 'score':28}]
l = sorted(d1, key=lambda x:(-x['score'], x['name']))
'''
# 输入
n = int(input())
# 构建排序原数组
a = []
for i in range(1,n+1):
c,m,e = map(int,input().split())
grade = c + m + e
a.append((grade,c,i))
# print(a)
# 自定义比较函数
def f_sort(elem):
return (-elem[0],-elem[1],elem[2])
# 排序,默认升序
a.sort(key=f_sort)
# 输出前五名
for tup in a[:5]:
print(f'{tup[2]} {tup[0]}')
4.5 二维列表排序
score = [[1000, 90], [3239, 88], [2390, 95], [7231, 84], [1005, 95], [1001, 88]]
score.sort(key=lambda x:-x[1]) # 按照第二个元素从大到小排序,把'-'去掉即为从小到大
# [[2390, 95], [1005, 95], [1000, 90], [3239, 88], [1001, 88], [7231, 84]]
score.sort(key=lambda x:(-x[1],x[0])) # 按照第二个元素从大到小排序,再根据第一个元素从小到大排序
# [[1005, 95], [2390, 95], [1000, 90], [1001, 88], [3239, 88], [7231, 84]]
score.sort(key=lambda x:(x[0] * x[1])) # 按照小列表内的乘积从小到大排序
五、日期处理
Python标准库模块datetime,python的内置标准库,不需要去下载。
datetime模块中常用的有5个类(date,time,datetime, timedelta,tzinfo)。
- date类:表示日期的类(年月日);
- time类:表示时间的类(时分秒);
- datetime类:表示日期时间的类(年月日时分秒);
- timedelta类:表示时间间隔,即两个时间点的间隔。用来计算两个datetime.datetime或者datetime.date类型之间的时间差;
- tzinfo类:时区的相关信息。
5.1 date类
date类有三个参数,创建 date对象=date(year,month,day),返回year-month-day。
>>> from datetime import *
>>> d = date(2023,5,8)
>>> d
datetime.date(2023, 5, 8)
date类对象的静态方法和字段 | 描述 |
---|---|
date.max、date.min | date对象所能表示的最大、最小日期 |
date.resolution | date对象表示日期的最小单位。这里是天 |
date.today() | 返回一个表示当前本地日期的date对象 |
date.fromtimestamp(timestamp) | 根据给定的时间戮,返回一个date对象 |
方法和属性 | 描述 |
---|---|
d1 = date(2011,06,03) | 返回date对象 |
d1.year、d1.month、d1.day | 年、月、日 |
d1.replace(year, month, day) | 生成一个新的日期对象,用参数指定的年,月,日代替原有对象中的属性 (原有对象仍保持不变) |
d1.timetuple() | 返回日期对应的time,struct_time对象 |
d1.weekday() | 返回周几,如果是星期一,返回0;如果是星期2,返回1,以此类推 |
d1.isoweekday() | 返回周几,如果是星期一,返回1;如果是星期2,返回2,以此类推 |
d1.isocalendar() | 返回格式如(year,month,day)的元组 |
d1.isoformat() | 返回格式如’YYYY-MM-DD’的字符串 |
d1.strftime(fmt) | 和time模块format相同 |
d1.ctime() | 返回格式如 Sun Apr 16 00:00:00 2021 |
应用实例:判断日期合法性函数。
def judge(x,y,z):
try:
s=datetime.date(x,y,z)
except:
print('日期不合法')
5.2 time类
time类有5个参数,创建 time对象=time(hour,minute,second,microsecond,tzoninfo),返回类似’08:29:30’,最后tzoninfo可选。
import datetime
ls = datetime.time(22,12,13,10)
print(ls)
# 22:12:13.000010
time类对象静态方法和字段 | 描述 |
---|---|
time.min、time.max | time类所能表示的最小、最大时间。其中,time.min = time(0, 0, 0, 0), time.max = time(23, 59, 59, 999999) |
time.resolution | 时间的最小单位,这里是1微秒 |
time类方法和属性 | 描述 |
---|---|
t1 = datetime.time(10,23,15) | 返回time对象 |
t1.hour、t1.minute、t1.second、t1.microsecond | 时、分、秒、微秒 |
t1.tzinfo | 时区信息 |
t1.replace([ hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] ] ) | 创建一个新的时间对象 与date类replace方法类似 |
t1.isoformat() | 返回型如"HH:MM:SS"格式的字符串表示 |
t1.strftime(fmt) | 同time模块中的format |
t1.tzname() | 返回时区名字 |
t1.utcoffset() | 返回时区的时间偏移量 |
5.3 datetime类
datetime类其实是可以看做是date类和time类的合体,其大部分的方法和属性都继承于这二个类。
# datetime类有很多参数,返回年月日,时分秒
d=datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])
静态方法和字段 | 描述 |
---|---|
datetime.today() | 返回一个表示当前本地时间的datetime对象 |
datetime.now([tz]) | 返回一个表示当前本地时间的datetime对象,如果提供了参数tz, 则获取tz参数所指时区的本地时间 |
datetime.utcnow() | 返回一个当前utc时间的datetime对象;格林威治时间 |
datetime.fromtimestamp(timestamp[, tz]) | 根据时间戮创建一个datetime对象,参数tz指定时区信息 |
datetime.utcfromtimestamp(timestamp) | 根据时间戮创建一个datetime对象 |
datetime.combine(date, time) | 根据date和time,创建一个datetime对象 |
datetime.strptime(date_string, format) | 将格式字符串转换为datetime对象 |
方法和属性 | 描述 |
---|---|
dt=datetime.now() | 返回datetime对象 |
dt.year、month、day、hour、minute、second、microsecond、tzinfo | 同date和time类方法 |
dt.date() | 获取date对象 |
dt.time() | 获取time对象 |
dt. replace ([ year[ , month[ , day[ , hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] ] ] ] ]) | 同date和time类方法 |
dt. timetuple() | 同date和time类方法 |
dt. utctimetuple() | 同date和time类方法 |
dt. toordinal() | 同date和time类方法 |
dt. weekday() | 返回weekday,如果是星期一,返回0;如果是星期2,返回1,以此类推 |
dt. isocalendar() | 同date和time类方法 |
dt. isoformat([sep] ) | 同date和time类方法 |
dt. ctime() | 返回一个日期时间的C格式字符串,等效于time.ctime(time.mktime(dt.timetuple())) |
dt. strftime (format) | 同date和time类方法 |
5.4 timedelta类
timedelta用来计算两个datetime.datetime或者datetime.date类型之间的时间差。
def __new__(cls, days=0, seconds=0, microseconds=0,milliseconds=0, minutes=0, hours=0, weeks=0)
从构造函数中来看,参数可选:days、seconds、microseconds(微秒)、milliseconds(毫秒)、minutes、hours、weeks,且默认是0。
应用实例:
import datetime
# 1. 查询300天前是几月几号
now = datetime.datetime.now().date()
delta = datetime.timedelta(days = 300)
print(now - delta)
# 输出结果
# 2021-05-07
# 2. datetime.timedelta()也可以多个参数,比如计算300天12小时前的时间
delta = datetime.timedelta(days = 300,hours = 12)
print(now - delta)
#输出结果
# 2021-05-06 23:51:36.405974
# 3. 计算总天数和秒数
datetime.timedelta(days=1,hours = 2).days # 1
datetime.timedelta(days=1,hours = 2).total_seconds() # 93600.0
# 4.设置时间间隔 以天为单位
delta=datetime.timedelta(days=1)
5.5 时区类tzinfo
备赛刷题过程中基本没用过。
六、找出现次数最多的元素
Python标准库模块collections,使用collections 模块的 Counter 类,返回字典对象。
Counter,顾名思义是一个 计数器。Counter 类作为一个无序的容器类型,以字典的 key-value 对形式存储元素,旨在统计各元素 出现的次数。
具体而言,key 表示元素,value 表示各元素 key 出现的次数,可为任意整数 (即包括0与负数)。
蓝桥杯真题:字符统计。
问题描述
给定一个只包含大写字母的字符串 S,请你输出其中出现次数最多的字符。
如果有多个字母均出现了最多次, 按字母表顺序依次输出所有这些字母。
输入格式
一个只包含大写字母的字符串S.
输出格式
若干个大写字母,代表答案。
样例输入
BABBACAC
样例输出
AB
from collections import Counter
string = input()
cnt = Counter(string)
# 最大次数
max_cnt = max(cnt.values())
# 使用视图对象items()遍历字典速度更快
ans = []
for k,v in cnt.items():
if v == max_cnt:
ans.append(k)
ans.sort()
print(''.join(ans))
应用实例:统计字符串中不同数字出现的次数,按数字的大小排序输出。
from collections import Counter
# N = input()
N = '134567894513543219'
# 统计每种不同的个位数字出现的次数
dic = Counter(N)
# 按keys的升序输出
keys = sorted(dic.keys())
# 输出
for key in keys:
print(f'{key}:{dic.get(key)}')
# 结果
# 1:3
# 2:1
# 3:3
# 4:3
# 5:3
# 6:1
# 7:1
# 8:1
# 9:2
6.1 most_common() —— 元素按出现频数从大到小列出
Counter.most_common([n])
方法将返回一个 带元组(elem,count) 的 列表list
,其中包含前 n 个出现频数最高的元素及其出现次数,并按次数从大到小排列。 若 n 被省略或为 None,most_common() 将返回 Counter 对象中的所有元素。若元素计数值相等,则按首次出现的顺序排序:
>>> C = Counter(x=3, y=2, z=1, h=2)
>>> C
Counter({'x': 3, 'y': 2, 'h': 2, 'z': 1})
>>> C.most_common(1) # n=1
[('x', 3)]
>>> C.most_common(2) # n=2
[('x', 3), ('y', 2)]
>>> C.most_common(3) # n=3
[('x', 3), ('y', 2), ('h', 2)]
>>> C.most_common(4) # n=4
[('x', 3), ('y', 2), ('h', 2), ('z', 1)] # 'y' 与 'h' 出现频次均为 2, 但 'y' 先出现, 故前排
>>> C.most_common() # n ignored
[('x', 3), ('y', 2), ('h', 2), ('z', 1)] # 全排:从大到小
>>> C.most_common()[::-1] # n ignored
[('z', 1), ('h', 2), ('y', 2), ('x', 3)] # 全排:从小到大
七、去重复元素
Python中set集合是一个无序的不重复元素序列。
7.1 创建set集合
# 使用大括号{}直接创建set集合
A_set = {val1,val2,...}
# 或者set()函数创建
A_set = set(val1,val2,..)
# 空集合
A_set = set()
# 空字典
A_dict = {}
7.2 去重功能
basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
print(basket)
# {'orange', 'banana', 'pear', 'apple'}
# 常用给列表去重
l = [1,2,3,4,5,5,6,6]
l = list(set(l))
print(l)
# [1, 2, 3, 4, 5, 6]
八、转换
8.1 进制转换
1.转十六进制
a = hex(2) # 十进制2转十六进制 0x2
2.转换八进制
a = oct(2) # 十进制2转八进制 0o2
3.转二进制
a = bin(2) # 十进制2转二进制 0b10
4.其它进制 转 十进制
a = int(s,16)
这里的int(s,16)代表把16进制的s转化成10进制。这里特别要注意其中的 s 必须为字符串,如果你在其中不加任何设定的输入数字的话,他会自动认定为整数,这样肯定会报错的,所以说你可以使用引号或者将前面加上str()去进行一个字符串的转化:
a = int(str(3),16) # 16进制'3'转十进制
# 3
a = int('11',2) # 将二进制'11'转化为十进制
# 3
a = int('18',16) # 将16进制'18'转化为十进制
# 24
a = int('24',8) # 将八进制'24'转化为十进制
# 20
8.2 存储单位转换
二进位bit
字节1Byte=8个二进位
1KB=1024B
1MB=1024KB
1GB=1024MB
1TB=1024GB
九、规律公式
9.1 有(无)向图的边数问题
有向图:n个节点,最多有 n * (n-1) 条边,最少 n 条边。
无向图:n个节点,最多有 n*(n-1) / 2 条边,最小 n-1 条边(没有自环和重边)。
9.2 .二叉树 叶子数问题
一颗树包含有n个结点的二叉树,最多包含多少个叶结点?
叶结点:(n+1)/2
十、必备函数
10.1 gcd() 函数
gcd(最大公约数) 可以直接用来去求最大公约数,需要调用math库:
import math
print(math.gcd(12,6)) # 返回参数a和b的最大公约数/因数,可以返回负数
# 6
10.2 lcm() 函数
而最小公倍数函数lcm() 不可以直接用,可以通过gcd()函数间接求出来:
a*b = gcd(a,b) * lcm(a,b),即:lcm(a,b) = a * b / gcd(a,b)
import math
def lcm(a,b):
return a // math.gcd(a,b) * b # 先做除法再做乘法,防止溢出,降低时间复杂度
10.3 factorial 阶乘函数
求n的阶乘大小
import math
print(math.factorial(n))
# 求n的阶乘大小
10.4 排列 permutations + 组合 combinations 函数
数学中常说的排列组合问题:
1)组合:itertools.combinations() 用法
import itertools
for j in (itertools.combinations('abcd', 3)):
print(j)
print(''.join(j))
# ('a', 'b', 'c')
# ('a', 'b', 'd')
# ('a', 'c', 'd')
# ('b', 'c', 'd')
# abc
# abd
# acd
# bcd
combinations() 是可以对集合或字符串进行组合(会去重)
# 用法与permutations相同,下面说说不同点:
from itertools import combinations, permutations
data = [1,2,3,4]
for combination in combinations(data,2):
print(combination) # 会去重
(1, 2)
(1, 3)
(1, 4)
(2, 3)
(2, 4)
(3, 4)
for permutation in permutations(data,2):
print(permutation) # 不会去重
(1, 2)
(1, 3)
(1, 4)
(2, 1)
(2, 3)
(2, 4)
(3, 1)
(3, 2)
(3, 4)
(4, 1)
(4, 2)
(4, 3)
2)排列:itertools.permutations() 用法
import itertools
for i in itertools.permutations('abc'):
print(i)
# ('a', 'b', 'c')
# ('a', 'c', 'b')
# ('b', 'a', 'c')
# ('b', 'c', 'a')
# ('c', 'a', 'b')
# ('c', 'b', 'a')
应用实例:数字1~9全排列。
import itertools
for i in itertools.permutations([x for x in range(1,10)]):
print(i)
permutations() 是可以对集合或字符串进行排序(不会去重,与combinations不同)
from itertools import permutations
b = [1,2,3] #对列表进行permutations排列
a = 'abc' #对字符串进行permutations排列
for j in permutations(b,3):
print (''.join('%d'%o for o in j)) # 123 132 213 231 312 321
for i in permutations(a,3):
x = ''.join(i)
print (x,end=' ') # abc acb bac bca cab cba
10.5 pow() 幂函数 快速幂
1)pow(x,y)
表示求解x的y次幂
print(pow(2,3)) # 2的3次方是多少
# 8
2)快速幂运算:pow(x,y,z)
表示求解x的y次幂对z取余后的结果
print(pow(2,3,5)) # 2的3次方是8,然后8再对5进行取余处理
# 3
3)对于取模运算,有如下公式:
注意:乘,矩阵乘,除,整除,取余(*, @, /, //, %)是同优先级运算符。
(a + b) mod k = (a mod k + b mod k) mod k
(a - b) mod k = (a mod k - b mod k + k) mod k
(a * b) mod k = ((a mod k ) * (b mod k)) mod k,使用后面的形式会降低时间复杂度
x / d % m = x % ( d × m ) / d
10.6 判断质数/素数函数 素数筛
1)素数/质数定义:只能被1和自己整除的正整数。
注意:1不是素数,最小的质数是2。
# 函数功能:判断一个数是否为素数
def is_prime(num):
if num < 2:
return False
for i in range(2, int(num ** 0.5) + 1):
if num % i == 0:
return False
return True
2)素数筛
素数的筛选:给定n,求2~n(包含n)内所有的素数。
注意:一个个地判断很慢,所以用筛子筛所有的整数,把非素数筛掉,剩下的就是素数。常用两种筛法:埃氏筛、欧拉筛。
# getPrimes函数功能:埃氏筛出2~n(包含n)的所有素数
# 返回:素数列表、素数个数
def getPrimes(n):
primes=[0]*n # 存放素数列表
cnt = 0 # 计数,索引
bprime = [False]*(n+1) # 非素数列表,n+1防止索引越界
# 0和1是非素数
bprime[0] = True
bprime[1] = True
for i in range(2,n+1):
if not bprime[i]: # 是素数
primes[cnt] = i
cnt += 1
for j in range(i*2,n+1,i): # 筛掉 i 的倍数,均为非素数
bprime[j] = True
return primes,cnt
# 输入
N = int(input())
primes,count = getPrimes(N)
# 输出
for p in primes:
if p == 0:
print()
break
print(p,end=' ')
print(count)
10.7 判断闰年函数
闰年:一年366天,2月有29天。年份能被4整除且不能被100整除、或者能被400整除的年是闰年。
# 判断闰年函数
def isLeapyear(year):
if (year % 4 == 0 and year % 100 != 0) or year % 400 == 0:
return True
else:
return False
10.8 分解质因数
算术定理:任何一个正整数n都可以唯一地分解为有限个素数的乘积:n = p1^c1*p2^c2...*pm^cm
,其中ci都是正整数(素数pi的个数),pi都是素数且从小到大。
factor(n)
函数模板:将正整数n分解质因数。
# 函数功能:将正整数n分解质因数
# 返回:p质因子列表、c质因子个数列表、m整数索引(几种质因子)
def factor(n):
p = [0]*20 # p[]记录因子,p[1]是最小因子。一个int数的质因子最多有10几个
c = [0]*40 # c[i]记录第i个因子的个数。一个因子的个数最多有30几个。
m = 0 # 索引
# 找质因子和质因子个数
for i in range(2,int(n ** 0.5)+1):
if n % i == 0:
m += 1
p[m],c[m] = i,0
while n % i == 0:
n //= i
c[m] += 1
if n > 1: # 没有除净,最后的n也是一个质数
m += 1
p[m],c[m] = n,1
return p,c,m
参考博客:
欢迎点赞评论,指出不足,笔者由衷感谢!~