当前位置:首页>python>两周速成|蓝桥杯python组(一)IO篇

两周速成|蓝桥杯python组(一)IO篇

  • 2026-09-19 20:19:19
两周速成|蓝桥杯python组(一)IO篇

IO篇

很多Python选手在平时练习时习惯用 input() 和 print(),到了赛场上却发现:

  • 程序运行时间超限,明明算法复杂度没问题;

  • 输出格式莫名错误,判题系统无情地给了0分。

原因很简单:Python的输入输出(IO)速度远慢于C/C++,且格式要求极其严格。如果你忽略了IO优化,即使算法正确也可能被卡掉。


为什么输入处理很重要?

  • 速度差异:sys.stdin.readline() 比 input() 快约5-10倍;sys.stdin.read() 一次性读入全部再解析,对于大数据最快。
  • 格式陷阱:输入可能包含多余空格、换行,甚至空行,需要稳健处理。
  • 多组测试数据:蓝桥杯有的题目是多组输入,直到EOF结束。

三种主要输入方式

1. input() —— 简单场景

  • 适合单行、少量输入
  • 返回字符串,需自行转换类型
  • 缺点:在循环中使用多次会导致超时
n = int(input())                # 读取整数
a, b = map(int, input().split()) # 读取一行两个整数
data = list(map(int, input().split())) # 读取一行多个整数

2. sys.stdin.readline() —— 推荐日常使用

  • 需要 import sys
  • 注意:返回的字符串包含末尾换行符\n,通常使用.strip()去除。但若输入本身含有空格(如字符串),.strip()会删掉首尾空格,此时用.rstrip('\n')更安全。
  • 适用:绝大多数题目,建议作为默认选择。
import sys
n = int(sys.stdin.readline())
a, b = map(int, sys.stdin.readline().split())
data = list(map(int, sys.stdin.readline().split()))

3. sys.stdin.read() —— 极致速度

  • 一次性读取所有输入,返回一个大字符串
  • 然后使用.split()分割成列表,再迭代处理
  • 优点:一次性读入全部内容,速度最快,尤其适合大数据量(10^5以上)。
  • 缺点:占用较多内存,且需要手动管理迭代器。
  • 适用:输入量巨大、行数不固定或需要整体解析的场景。
import sys
data = sys.stdin.read().split()
it = iter(data)
n = int(next(it))
arr = [int(next(it)) for _ in range(n)]

输入常用模板

模板1:读取单行多个整数(一行内)

import sys
a, b, c = map(int, sys.stdin.readline().split())

模板2:读取n行,每行一个整数

n = int(sys.stdin.readline())
arr = [int(sys.stdin.readline()) for _ in range(n)]

模板3:读取n行,每行多个整数

n = int(sys.stdin.readline())
matrix = [list(map(int, sys.stdin.readline().split())) for _ in range(n)]

模板4:未知行数,直到EOF

import sys
for line in sys.stdin:
ifnot line.strip():
continue# 跳过空行
    a, b = map(int, line.split())
# 处理

或者使用sys.stdin.read().split()一次性处理。

模板5:处理多组测试数据,每组第一行是n,接下来n行

import sys
data = sys.stdin.read().split()
it = iter(data)
whileTrue:
try:
        n = int(next(it))
except StopIteration:
break
    arr = [int(next(it)) for _ in range(n)]
# 处理当前组

输入常见坑点

  • 换行符残留:sys.stdin.readline() 记得 strip(),否则数字转int时不会报错,但字符串比较可能出问题。
  • 空行处理:输入中可能有空行,直接用 line.split() 会得到空列表,用 if not line.strip(): continue 跳过。
  • 递归深度:使用DFS时,记得在开头设置 sys.setrecursionlimit(1000000),否则递归超过1000层会报错。

输出:细节决定满分

1. print() 的基本用法

print(a, b, c)          # 空格分隔,末尾换行
print(a, b, c, sep=',') # 逗号分隔,末尾换行
print(a, end=' ')       # 空格结尾,不换行

2. 格式化输出

使用 join —— 输出列表最优雅

arr = [1, 2, 3]
print(' '.join(map(str, arr)))   # 输出 "1 2 3"
  • 优点:一次性生成整行,避免循环打印,且行末无多余空格。

使用 f-string —— 灵活直观

name = "Alice"
age = 20
print(f"Name: {name}, Age: {age}")

pi = 3.1415926
print(f"{pi:.2f}")          # 保留两位小数 -> 3.14
print(f"{pi:10.2f}")        # 宽度10,右对齐 -> "      3.14"

使用 format 或 % (最好备选)

print("{:.2f}".format(pi))
print("%.2f" % pi)

3. 输出性能优化:告别循环 print

当输出行数较多(>1万行)时,循环调用 print 会导致大量IO操作,严重拖慢速度。必须采用批量输出。

低效写法

for i in range(100000):
    print(i)          # 10万次系统调用,极慢

高效写法

out_lines = []
for i in range(100000):
    out_lines.append(str(i))
sys.stdout.write('\n'.join(out_lines))

或者用 io.StringIO 构建大字符串:

import io
out = io.StringIO()
for i in range(100000):
    out.write(str(i) + '\n')
sys.stdout.write(out.getvalue())
  • 原理:print 内部会做类型转换和缓冲,且每次调用都涉及系统调用。批量输出只需一次系统调用,速度提升数倍甚至数十倍。

4. 输出格式陷阱清单

陷阱
正确做法
行末多余空格
使用 join 自动处理
每行结尾需要换行
print()
 默认换行,sys.stdout.write 需手动加 \n
布尔值大小写
Python输出 True/False,若题目要求 YES/NO,需手动转换
浮点数精度
使用 f-string 或 format 指定小数位数,避免用 round()
多组输出之间空行
用标志变量控制,第一组前不加空行,组间加 print()
调试信息混入输出
提交前删除或注释所有调试 print


自查清单

  • [ ] 是否使用了 sys.stdin.readline() 或 read() 代替 input()
  • [ ] 输入中可能含有空行,是否做了跳过处理
  • [ ] 大量输出时是否使用了批量写入(join 或 StringIO)
  • [ ] 行末有没有多余空格
  • [ ] 浮点数保留位数是否符合要求
  • [ ] 布尔值大小写是否正确(True/False 还是 YES/NO)
  • [ ] 递归函数前是否设置了 sys.setrecursionlimit
  • [ ] 是否删除了所有调试用的 print

作者的话

作者最近编程能力简直灾难性下降,对AI的依赖度越来越高。而且这一年早已不再练习算法,开始转向大型程序开发和前端设计,参加了许多项目、拿了软件专著,但现在让我真刀实枪去比赛算法,真的有些心虚……最后这两周快速拾起一下,以后说不定就没机会再参加编程比赛了。

IO部分是最容易拿分也最容易失分的地方。扎实掌握输入输出,不仅能稳稳拿到基础分,更能为复杂算法留出宝贵的运行时间。接下来两周的复习中,我还会陆续推出基本数据结构、标准库、搜索、动态规划、数论等专题,快速拾起状态。

最新文章

随机文章