蓝桥杯Python组必备代码利器(12个好用函数+数据结构分享)

1. 进制转换

首先,需要注意的是,不管转化为什么进制,要使用十进制作为中介,以下所有函数都是输入十进制数。

# 十进制
int('字符串') --> int类型变量
还可以加一个可选参数表示输入的字符串的进制,如:
int('101',2) --> 输出十进制5,在某些题目读入二进制数据极其好用!
# 二进制
bin(十进制数) --> 输出'0b'开头二进制数
# 八进制
oct(十进制数) --> 输出'0o'开头八进制数
# 十六进制
hex(十进制数) --> 输出'0x'开头十六进制数
# 转换不同进制
oct(int('0b1010')) # 二进制转八进制:要以十进制为转换中介

2. print()函数格式化输出

  1. 保留两位小数

    number = 3.14159 
    print(f"Number: {number:.2f}") 
    # 输出:Number: 3.14
    
  2. 数字补全为固定宽度

    # 补全为5位数,不足的部分用0填充
    number = 42
    print(f"Number: {number:05d}")
    # 输出:Number: 00042
    
  3. 补全任意符号,任意宽度的小数或整数

    number = 12.34
    print(f"Number: {number:x>7.2f}") 
    """
    x是要补全的符号
    ">"表示往前填充,"<"表示往后填充
    7 表示输出的宽度为 七位(包括小数点)
    .2f 表示保留小数点后两位
    """
    # 输出:Number: xx12.34
    

3. 快速数据读入

  1. 最常见的input()函数有两种基本操作:
# 读入较少的时候可以用map函数读入
a, b = map(eval, input().split()) # 第一种,得到单个变量
a = [int(i) for i in range(n)] # 第二种,得到一组数,速度较快
  1. 超快读入:另外如果需要读入超级大量的数据,需要使用sys库里边的读入函数,速度可快了~

    import sys
    n = int(input())
    for i in range(n):
        a, b = map(int, sys.stdin.readline().strip('\n'))
    

4. 取余操作

有的题目会要求把答案取余之后再输出,比如取余 109+7 再输出,这时候如果直接把余数写为:

MOD_NUM = 1e9 + 7

则得到的答案是浮点数,有小数点,不是int型,就会报错了。所以应该修改为:

MOD_NUM = int(1e9) + 7
or
MOD_NUM = 1000000007 # 数错可怎么办鸭!

5. 加快代码运行速度

使用全部变量的速度会比局部变量的速度慢,所以在运算量大概要爆炸的时候(如1e8),可以考虑使用调用函数的方式来加快程序的运行,如:

def main():
    pass
if __name__ == '__main__':
    main()

另外,还可以适当使用生成器表达式来加快运行速度,如下代码块所示。可以看到这里生成器表达式不一定要写成列表,因为生成器表达式返回的是一个迭代器,平常的写法将其转化为列表,所以外边加上了中括号。但是,使用生成器表达式太多会导致段错误,尽量不要嵌套使用。

f[i] = sum(f[i-1][v] for v in e[j])

6. 秒杀记忆化搜索

记忆化搜索是指在搜索的时候有可能多次重复搜索,这时候把之前搜索的结果记住,即可快速找到结果。python有一个系统自带的库实现:

from functools import lru_cache
@lru_cache(maxsize=None) # 这个参数虽然是None但是不能省略哦~否则size好小滴

7. 系统库自带二分查找

使用python自带的库bisect。!!!!!使用这个库的函数需要输入升序序列,如果没有升序,需要先升序,或者自己写二分查找。

bisect.bisect_left和bisect.bisect_right是两个二分查找的函数,区别在于序列中存在相等元素时的操作不同,如查找元素在序列[1,2,4,4,5]中的位置:

import bisect
a = [1,2,4,4,5]
print(bisect.bisect_left(a, 4) # 得到的答案是 2,表示如果a.insert(2, 4)是在相等的数字的最左边
print(bisect.bisect_right(a, 4) # 得到的答案是 4,表示如果a.insert(4, 4)会插入到相等的数字最右边

如果想要二分查找之后直接插入到序列里边,则可以使用bisect.insort_left()和bisect.insort_right()两个函数,如果对相等的元素没有特殊的要求,一般可以直接使用一个insort()就可以了哦,代码如下:

import bisect

a = [1, 3, 4, 7, 9]

bisect.insort(a, 5)
print(a)  # 输出: [1, 3, 4, 5, 7, 9]

bisect.insort(a, 0)
print(a)  # 输出: [0, 1, 3, 4, 5, 7, 9]

8. 系统库自带队列

这里的队列是使用C语言实现的,比使用列表模拟更快,在实现大量数据的操作时需要使用这个而不是列表

from collections import deque
d = deque()

d.append(1) # deque([1])
d.pop() # deque([])

d.leftappend(object)
d.leftpop()

d.insert(idx, value)

9. 取余后向上取整

# 若 a = 3, b = 5,想要a ➗ b 后向上取整:
ans = (a + b - K) // b # (3 + 5 - 1) // 5 == 7 // 5 == 1
# 或者
ans = (a - K) // b + 1
# 这里K需要取一个足够小的数,比b小就行,为的是防止 a == b的时候向上取整不对,需要减去一个足够小的数,但是又不能减去太大,减去比b大的数就会导致结果不对,所以K的取值是 0<K<b的

10. 秒杀多个数字的最大公因数

from math import gcd
gcd(4,6,8,10) # out: 2

排序的时候的自定义排序,使用functools库里边的cmp_to_key函数:

from functools import cmp_to_key

# 下列函数实现二维列表的自定义排序
def cmp(a, b):
    if a[0] < b[0]:
        return -1 # 希望 a[0] 在 b[0] 之前
    elif a[0] > b[0]:
        return 1 # 希望 a[0] 在 b[0] 之后
    else:
        if a[1] < b[1]:
            return -1
        else:
            return 1

myList = [[2,3,1],[4,5,-2],[2,5,2]]
myList.sort(key=cmp_to_key(cmp))
print(myList) 

11. math库 / collections库 极其好用的 函数 / 数据结构

import math
math.pi # Π
math.ceil() # 向上取整
math.floor() # 向下取整

from collections import Counter # 这个数据结构极其有用!!!经常拿来统计某些东西出现的次数,还能做简单的运算(相加相减)
from collections import defaultdict # 没有key值的时候会有默认值,再也不用怕没有初始化某个key值就报错啦
from collections import deque # 双向队列

12. 数据离散化

将离散的数据在不需要保留原本数值,而只需要用到数值之间的大小关系的时候,就可以用这一操作来减少数据覆盖的区间,一般给的数据是比较稀疏的,比如给了5000个数,但是覆盖的大小为1e9,这时候用树状数组或线段树来维护的区间大小显然1e9太大了,如果能够离散化,那么需要维护的大小就只有(0-4999),因此需要数据离散化。

# 数据li
from bisect import bisect_left

a = [132,165,46,51,315]
b = list(set(a))
b.sort()
dis_a = []
for i in range(len(a)):
    dis_a.append(bisect_left(b, a[i]))
print(dis_a) --> Out: [2, 3, 0, 1, 4]
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐