目录注意项常用库函数数学计算常用math库随机数*列表操作*字符串操作splitstrip集合操作元组操作字典操作类型转换普通转换join详解sort详解map详解filter详解切片切片基础切片赋值*引用与复制f-string 详解collections库竞赛常用itertools库竞赛常用enumerate 和 zip离线查询常用语法列表推导式生成器表达式匿名函数模板ACM模式IO按行取输入整体取输入一维列表传参输入二维列表传参输入输出常用技法字符串清洗只保留字母快速初始化二维数组多维数组内部序列去重来源三数之和二维数组按端点排序去重列表去重二维列表去重遍历时跳过重复字符串去重Counter去重统计*字符串倒置**字符串列表双重倒置字符串特定位置插入二分查找bisect详解二分查找模板转置矩阵链表二叉树种树遍历常见错误与优化技巧错误优化*查找优化排序二分 替代 线性查找哈希表 替代 双重循环前缀和 替代 重复求和双端队列 替代 暴力窗口双指针 替代 双重循环迭代 替代 递归滑动窗口 替代 暴力子串Counter 替代 手动统计注意项在 Python 中空的容器空列表、空字符串、空字典在if语句中等价于False。只要是可迭代的都能解包赋值但要注意数量必须匹配。常用库函数数学计算sum([1,2,3]) # 6 求和 max([1,2,3]) # 3 最大值 min([1,2,3]) # 1 最小值 abs(-5) # 5 绝对值 pow(2, 10) # 1024 次方 round(3.14159, 2) # 3.14 四舍五入常用math库import math math.sqrt(9) # 3.0 开平方 math.ceil(3.2) # 4 向上取整 math.floor(3.8) # 3 向下取整 math.pi # 3.14159... math.inf # 无穷大随机数import random # 生成0到10之间的随机整数包括0和10 print(random.randint(0, 10)) # 生成1到10之间不包括10的随机整数 print(random.randrange(1, 10)) # 生成0到1之间的随机浮点数不包括1 print(random.random()) # 生成1到3之间的随机浮点数 print(random.uniform(1, 3)) # 特定序列随机选择元素 list1 [1, 2, 3, 4, 5] random_element random.choice(list1) # 从列表中随机选择3个不重复的元素 print(random.sample(list1 , 3)) # 序列随机排序 list1 [1, 2, 3, 4, 5] random.shuffle(list1) # 正态分布 print(random.normalvariate(0, 1))*列表操作a [3,1,2] len(a) # 3 长度 sorted(a) # [1,2,3] 排序不改变原列表 sorted(a, reverseTrue) # [3,2,1] 倒序 a.sort() # 直接改变原列表 s.reverse() # 倒置 a.append(4) # 末尾添加 a.pop() # 删除末尾 a.pop(2) # 弹出下标2 → 1 a.count(3) # 统计3出现次数 a.index(3) # 3第一次出现的下标 del my_list[1] # 删除索引 1 的元素 a.remove(a) # 根据元素值进行删除 sum(a) # 求和 a[-1]# 看最后一个。 a[0]# 看第一个。*字符串操作s Hello123 # 判断类型 s.isalnum() # True 全是字母或数字 s.isalpha() # False 全是字母 s.isdigit() # False 全是数字 s.islower() # False 全是小写 s.isupper() # False 全是大写 s.isspace() # False 全是空白 # 大小写转换 s.lower() # hello123 s.upper() # HELLO123 # 查找 s.count(l) # 2 s.find(l) # 2 找不到返回-1 s.index(l) # 2 找不到报错 # 替换 str.replace(old, new[, max]) # 可选字符串, 替换不超过 max 次 ord(a) # 97 字符转ASCII码 chr(97) # a ASCII码转字符split注返回列表# 智能分割把所有的连续空白符换行 \n、空格、制表符 \t都当成切分符并且会自动忽略掉开头和结尾的空元素。 s.split() s.split() # [1, 2, 3] 默认按空格切 s.split( ) # [1, 2, 3] 指定空格切 s.split(\n) # [1 2 3] 按换行符切strip注返回字符串s.strip() # 去首尾空白 s.strip() # hello 两端都去 s.lstrip() # hello 只去左边 s.rstrip() # hello 只去右边 ***hello***.strip(*) # hello 123hello123.strip(123) # hello集合操作set1 {1, 2, 3, 4} # 直接使用大括号创建集合 set2 set([4, 5, 6, 7]) # 使用 set() 函数从列表创建集合 # 创建一个空集合必须用 set() 而不是 { }因为 { } 是用来创建一个空字典 s.add(4) # 添加元素 → {1,2,3,4} s.remove(1) # 删除元素找不到报错 s.discard(1) # 删除元素找不到不报错 len(s) # 元素个数 3 in s # True 判断是否存在 3 not in s # False a | b # {1,2,3,4} 并集 a b # {2,3} 交集 a - b # {1} 差集a有b没有 a ^ b # {1,4} 对称差集只在一个里面的 s[0] # ❌ 报错集合没有下标 list(s)[0] # ✅ 转成列表再取元组操作# 创建 t (1, 2, 3) t (1,) # 单元素元组必须加逗号 t 1, 2, 3 # 省略括号也可以 t tuple([1,2,3]) # 列表转元组 # 取值 t (1, 2, 3, 4, 5) t[0] # 1 t[-1] # 5 t[1:3] # (2, 3) t[::-1] # (5,4,3,2,1) t (1, 2, 2, 3) len(t) # 4 t.count(2) # 2 统计出现次数 t.index(2) # 1 第一次出现的下标 2 in t # True max(t) # 3 min(t) # 1 sum(t) # 8字典操作# 字典可以判相等 顺序不影响键值对一样就相等 d {a: 1, b: 2, c: 3} d {} # 空字典 d dict() # 空字典 d[a] # 1 d.get(a) # 1 d.get(a0) # 找不到不报错 d[b] 2 # 添加/修改 del d[a] # 删除找不到报错 d.pop(a) # 删除并返回值找不到报错 d.pop(a, 0) # 找不到返回0不报错 d.clear() # 清空 for key in d: # 遍历key print(key) # a b for key, val in d.items(): # 遍历key和value print(key, val) # a 1 / b 2 for val in d.values(): # 只遍历value print(val) # 1 2 for key in d.keys(): # 只遍历key print(key) # a b len(d) # 2 元素个数 a in d # True 判断key是否存在 d.keys() # 所有key d.values() # 所有value d.items() # 所有键值对类型转换普通转换int(123) # 123 float(3.14) # 3.14 str(123) # 123 list(abc) # [a,b,c] list((1,2,3)) # [1,2,3]join详解分隔符.join(元素) #列表、字符串、元组、字典 a [a, b, c] .join(a) # abc 无缝拼接 .join(a) # a b c 空格分隔 ,.join(a) # a,b,c 逗号分隔 -.join(a) # a-b-c 横线分隔 a [1, 2, 3] .join(a) # ❌ 报错元素是数字 .join(map(str, a)) # ✅ 1 2 3 #join与split互逆 # split字符串 → 列表 a b c.split() # [a, b, c] # join列表 → 字符串 .join([a,b,c]) # a b csort详解# !!!.sort()返回None list.sort(cmpNone, keyNone, reverseFalse) # cmp -- 可选参数, 如果指定了该参数会使用该参数的方法进行排序。 # key -- 用来进行比较的元素具体的函数的参数就是取自于可迭代对象中指定可迭代对象中的一个元素来进行排序。 # reverse -- 排序规则reverse True 降序 reverse False 升序默认。 my_list.sort(keylen) sorted_list sorted(my_list, keylambda x: x[-1])map详解map(function, iterable, ...) # function要作用于可迭代对象如列表、元组等每个元素的函数。 # iterable一个或多个可迭代对象。 ## 返回一个map对象必须通过转化为list或其他可迭代类型来查看结果。 # 字符串列表转整数 map(int, [1,2,3]) # 1 2 3 list(map(int, [1,2,3])) # [1, 2, 3] # 整数列表转字符串 map(str, [1, 2, 3]) # 1 2 3 list(map(str, [1, 2, 3])) # [1, 2, 3] # 转浮点数 list(map(float, [1.1,2.2])) # [1.1, 2.2]filter详解filter(function, iterable) # function用于筛选元素的函数该函数应返回一个布尔值表示元素是否符合筛选条件。 # iterable待筛选的序列可以是列表、元组、集合等可迭代对象。 # 返回值filter函数返回一个由符合条件的元素组成的新列表。 numbers [1, 2, 3, 4, 5, 6, 7, 8, 9] even_numbers filter(lambda x: x % 2 0, numbers) print(list(even_numbers)) # Output: [2, 4, 6, 8]切片切片基础切片可以用在字符串列表及元组上。# 格式[start : end : step] a [0, 1, 2, 3, 4, 5] s 012345 a[1:3] # [1, 2] 从1取到2取不到3 a[:3] # [0, 1, 2] 从头取到2 a[2:] # [2, 3, 4, 5] 从2取到末尾 a[:] # 全部 a[-1] # 5 最后一个 a[-2:] # [4, 5] 最后两个 a[:-2] # [0,1,2,3] 除了最后两个 # 带步长 a[::2] # [0, 2, 4] 每隔一个 a[::3] # [0, 3] 每隔两个 a[::-1] # [5,4,3,2,1,0] 倒序 a[4:1:-1] # [4, 3, 2] 从4倒着取到2 # 负数 a[-1] # 最后一个 a[-2] # 倒数第二个 a[-3:] # 最后三个切片赋值# 把切片放在赋值语句的左边或把它作为del操作的对象 # 就可以对序列进行嫁接、切除或就地修改操作。 a[:] [4, 5, 6] # 直接修改原列表内容*引用与复制# 引用同一个对象 b a # 复制 b a[:] # 浅复制 b a.copy() # 浅复制 b list(a) # 浅复制 import copy b copy.deepcopy(a) # 深复制 # 浅拷贝与深拷贝 # 一维列表 → 浅拷贝就够了 a [1, 2, 3] b a[:] # 二维列表 → 用深拷贝或列表推导式 import copy b copy.deepcopy(a) # 或者列表推导式更常用 b [row[:] for row in a]f-string 详解# 变量 name 小明 age 18 print(f我叫{name}今年{age}岁) # 我叫小明今年18岁 # 数字 x 3.14159 f{x:.2f} # 3.14 保留2位小数 f{x:.0f} # 3 保留0位小数 f{x:10.2f} # 3.14 总宽度10右对齐 f{x:10.2f} # 3.14 总宽度10左对齐 f{x:010.2f} # 0000003.14 总宽度10用0补齐 # 整数 n 42 f{n:5d} # 42 总宽度5右对齐 f{n:5d} # 42 总宽度5左对齐 f{n:05d} # 00042 总宽度5用0补齐 # 字符串 s hi f{s:10s} # hi 总宽度10左对齐 f{s:10s} # hi 总宽度10右对齐 f{s:^10s} # hi 总宽度10居中collections库竞赛常用from collections import Counter, defaultdict, deque # Counter 统计频率 c Counter([1,1,2,3]) # 返回一个字典{1:2, 2:1, 3:1} c.most_common(2) # [(3, 3), (2, 2)] # 出现最多的N个 # defaultdict 带默认值的字典 d defaultdict(int) # 默认值为0不会报KeyError d[a] 1 # deque 双端队列 q deque([1,2,3]) q.appendleft(0) # 左边添加 q.popleft() # 左边删除 d.count(a) # 计算 deque 中元素等于 x 的个数。 a.extend(b) # 在a队列右侧添加另一个iterable参数b中的元素。 d.index(w) # 返回索引找不到则报错 a.insert(1,X) # 插入 a.remove(a) # 移除找到的第一个值。 # 向右循环移动 d deque(ghijkl) d.rotate(1) # -1是往左循环移动 # deque([l, g, h, i, j, k])itertools库竞赛常用# 全排列 from itertools import permutations ls [] for item in permutations(nums): ls.append(item) return ls # 组合取2个 print(list(combinations(l, 2))) # [(1,2), (1,3), (2,3)] # 前缀和 from itertools import accumulate s list(accumulate(a)) print(s) # [1, 3, 6, 10, 15]enumerate 和 zip# enumerate 带下标遍历 for i, x in enumerate([10,20,30]): print(i, x) # 0 10 / 1 20 / 2 30 # zip按位置解包 同时遍历两个列表 a [1,2,3] b [4,5,6] for x, y in zip(a, b): print(x, y) # 1 4 / 2 5 / 3 6离线查询# 查询某函数用法 help(sorted) # 查询某类型下的方法 help(int) # 列出某类型的所有方法 dir(float)常用语法列表推导式# 先生成整个列表再求和 [表达式 for 变量 in 可迭代对象 if 条件] [表达式 if 条件 else 表达式 for 变量 in 可迭代对象 ] result [x for x in a if x ! 0] nums [x if x % 2 0 else 0 for x in range(10)]生成器表达式colors [Black, White, Yellow] sizes [XS, S, M, L, XL] t_shirt_models ((color, size) for color in colors for size in sizes) # 嵌套循环 print(t_shirt_models) # Output:generator object genexpr at 0x0000020CE2EC4C48 #由于输出迭代器因此生成器表达式后一般跟类型转换 # 取数据 for t in t_shirt_models: print(t)匿名函数lambda arguments: expression # arguments 是参数列表可以包含零个或多个参数但必须在冒号(:)前指定。 # expression 是一个表达式用于计算并返回函数的结果。 x lambda a : a 10 print(x(5)) # 15模板ACM模式IO按行取输入import sys for line in sys.stdin: if not line.strip(): continue tyr: nums list(map(int, line.split())) a nums[0] b nums[1] res a b print(res) except: break整体取输入import sys data sys.stdin.read().splitlines() idx 0 # 分组取 # for _ in range(t): # 然后按需要一行一行取 line1 data[idx]; idx 1 # 如果输入的是列表 line1 eval(data[idx]): idx 1一维列表传参输入智能分割所有空白格data sys.stdin.read().split() res process(list(map(int, data)))按行分割# 或者这里可以直接用splitlines()后续就不用条件过滤 data sys.stdin.read().split(\n) res process([int(line) for line in data if line.strip()])二维列表传参输入注split(\n)切割后最后会多出空行因此必须使用line.strip()过滤data sys.stdin.read().split(\n) res process([list(map(int, line.split())) for line in data if line.strip()])输出# 加分隔符输出 print(a, b, sep \n) # 三引号多行输出 print(aaa bbb ccc) # 列表输出转换 print( .join(map(str, sorted(nums)))) # 数字列表先转换为字符列表后再空格拼接常用技法字符串清洗只保留字母# 字符清洗只保留字母 string for char in data: if a char z or A char Z: char char.lower() string char快速初始化二维数组ls [[0] * m for _ in range(n)]快速初始化整数序列# 1到n l list(range(1, n1)) # [1, 2, 3, 4, 5] # 带步长 l list(range(0, 20, 2)) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]多维数组内部序列去重三数之和res set() for item in permutations(nums, 3): res.add(tuple(sorted(item))) # 集合元素必须可哈希因此要先转换为元组二维数组按端点排序# 使用匿名函数按每个子序列第一个元素大小排列 ls.sort(keylambda x: x[0])环形下标n 5 # 环形遍历从某位置往后走k步 idx (idx k) % n # 约瑟夫环数m个人 idx (idx m - 1) % len(people) # 循环数组下一个位置 next_idx (i 1) % n # 循环数组上一个位置 prev_idx (i - 1 n) % n # 星期几今天是dayk天后是 day (day k) % 7去重列表去重a [1,2,2,3,3,4] # 方法1set最简单 list(set(a)) # [1,2,3,4] 顺序不保证 # 方法2保留顺序去重 list(dict.fromkeys(a)) # [1,2,3,4] 保留原顺序 # 方法3列表推导式 res [] [res.append(x) for x in a if x not in res] # [1,2,3,4]二维列表去重a [[1,2],[1,2],[3,4]] # 转tuple加入集合 res set(tuple(x) for x in a) [list(x) for x in res] # [[1,2],[3,4]] # 或者 list(map(list, set(map(tuple, a))))遍历时跳过重复nums [1,1,2,2,3] nums.sort() for i in range(len(nums)): if i 0 and nums[i] nums[i-1]: continue # 跳过重复 print(nums[i]) # 1 2 3字符串去重s aabbcc # 去重保留顺序 .join(dict.fromkeys(s)) # abc # 去重不保留顺序 .join(set(s)) # 顺序不保证Counter去重统计from collections import Counter a [1,1,2,2,3] Counter(a).keys() # dict_keys([1,2,3]) 去重 list(Counter(a)) # [1,2,3]*字符串倒置s abcde s[::-1] # 直接倒置 .join(reversed(s)) # 空字符连接倒置**字符串列表双重倒置data[idx] abc def str [s[::-1] for s in data[idx].split()][::-1]字符串特定位置插入s hello # 在下标2的位置插入XYZ s s[:2] XYZ s[2:] # he XYZ llo heXYZllo二分查找bisect详解from bisect import bisect_left, bisect_right, insort bisect_left(a, x) # x位置有重复值时左边 bisect_right(a, x) # x位置有重复值时右边 insort(a, x) # 插入x并保持有序 # 插入元素4 bisect.insort_left(sorted_list, 4)二分查找模板# 二分查找模板 from bisect import bisect_left # 在有序数组中找 x a.sort() pos bisect_left(a, x) if pos len(a) and a[pos] x: print(fFound at index {pos})转置矩阵# n行m列 -- m行n列 n, m map(int, data[idx].split()); idx 1 mat [] for _ in range(n): mat.append(list(map(int, data[idx].split()))); idx 1 # 转置 mat_c [[mat[j][i] for j in range(n)] for i in range(m)]# zip按位置解包 mat_c [list(row) for row in zip(*mat)]链表import sys class ListNode: def __init__(self, x): self.val x self.next None # 把 {1,2,3} 转成链表 def build(s): s s[1:-1] if not s: return None vals s.split(,) head ListNode(int(vals[0])) cur head for v in vals[1:]: cur.next ListNode(int(v)) cur cur.next return head # 反转 def reverse(head): p, c None, head while c: c.next, p, c p, c, c.next return p # 输出 def print_list(head): res [] while head: res.append(str(head.val)) head head.next print({ ,.join(res) }) # 你的输入方式 data sys.stdin.read().splitlines() idx 0 head build(data[idx]); idx 1 new_head reverse(head) print_list(new_head)二叉树种树import sys class TreeNode: def __init__(self, x): self.val x self.left None self.right None # 把 {1,2,3,#,#,4,5} 转成二叉树层序构建 def build(s): s s[1:-1] if not s: return None vals s.split(,) root TreeNode(int(vals[0])) queue [root] idx 1 while queue and idx len(vals): node queue.pop(0) # 左孩子 if idx len(vals) and vals[idx] ! #: node.left TreeNode(int(vals[idx])) queue.append(node.left) idx 1 # 右孩子 if idx len(vals) and vals[idx] ! #: node.right TreeNode(int(vals[idx])) queue.append(node.right) idx 1 return root # 你的输入方式 data sys.stdin.read().splitlines() idx 0 root build(data[idx]); idx 1遍历# 四种遍历 # 前序根→左→右 def preorder(root): if not root: return [] return [root.val] preorder(root.left) preorder(root.right) # 中序左→根→右 def inorder(root): if not root: return [] return inorder(root.left) [root.val] inorder(root.right) # 后序左→右→根 def postorder(root): if not root: return [] return postorder(root.left) postorder(root.right) [root.val] # 层序一层一层从左到右 def levelorder(root): if not root: return [] res [] queue [root] while queue: node queue.pop(0) res.append(node.val) if node.left: queue.append(node.left) if node.right: queue.append(node.right) return res常见错误与优化技巧错误部分用例超时循环中变量未重置全局变量初始化问题如含负数但仍初始化为0strip()返回字符串后[0]取出的是单个字符split()返回字符列表后[]取的是字符串复制与引用list赋值是引用修改会互相影响append列表要副本用[:]复制一份二维初始化用推导式不用*号回溯结果存path[:]不存path函数内改列表用[:]赋值不用无输出结果检查输出类型是否正确.join()只接受字符型可迭代对象优化*查找优化# ❌ 列表查找 O(n) if x in list # ✅ 集合/字典查找 O(1) if x in set if x in dict排序二分 替代 线性查找数组查找下标# ❌ 线性查找 O(n) nums.index(x) # ✅ 排序后二分 O(log n) from bisect import bisect_left pos bisect_left(nums, x)哈希表 替代 双重循环两数之和、A-BC数对# ❌ 暴力双循环 O(n²) for i in range(n): for j in range(i1, n): # ✅ 哈希表 O(n) seen {} for i, val in enumerate(nums): if target - val in seen: return [seen[target-val], i] seen[val] i前缀和 替代 重复求和# ❌ 每次重新求和 O(n) sum(nums[i:j]) # ✅ 前缀和 O(1)查询 prefix [0] * (n1) for i in range(n): prefix[i1] prefix[i] nums[i] # 区间[i,j]的和 prefix[j1] - prefix[i]双端队列 替代 暴力窗口# ❌ 每次取max O(k)总体O(nk) max(nums[i:ik]) # ✅ 双端队列 O(n) from collections import deque dq deque() # 存下标保持递减双指针 替代 双重循环# ❌ 暴力 O(n²) for i in range(n): for j in range(i1, n): # ✅ 双指针 O(n) left, right 0, len(nums)-1 while left right: if 满足条件: left 1 right - 1迭代 替代 递归# ❌ 递归 n1000崩溃 def fib(n): return fib(n-1) fib(n-2) # ✅ 迭代 a, b 0, 1 for _ in range(n): a, b b, ab滑动窗口 替代 暴力子串# ❌ 暴力 O(n²) for i in range(n): for j in range(i, n): # ✅ 滑动窗口 O(n) left 0 for right in range(len(s)): while 不满足条件: left 1Counter 替代 手动统计# ❌ 手动统计 d {} for c in s: d[c] d.get(c, 0) 1 # ✅ Counter一行搞定 from collections import Counter Counter(s)