电子学会🐍 Python🔧 C++GESP🐍 Python🔧 C++
__CRUMBS__

CCF GESP 编程能力等级认证(Python)· 知识点手册

依据《CCF 编程能力等级认证 C++&Python 认证标准》整理。GESP 由中国计算机学会主办,Python 编程认证共一至八级,从编程入门到图论与算法优化逐级递进。每个知识点均配有详细讲解、Python 代码示例、易错点提示,并配模拟题讲解;难懂处附适合小学生、初中生的生活化例子。

共 8 个等级题型:15 单选 + 10 判断 + 2 编程1-4 级 120 分钟 · 5-8 级 180 分钟附各等级模拟题

考纲总览

等级递进 · 能力要求 · 题型说明

一、等级逻辑关系总览

《CCF 编程能力等级认证 C++&Python 认证标准》由中国计算机学会(CCF)制定,认证划分为一至八级,' '为学习者提供编程能力水平的证明。考试采用上机考试,题型为单选题(15 道 × 2 分)+ 判断题(10 道 × 2 分)+ 编程题(2 道 × 25 分),' '1-4 级考试时间 120 分钟,5-8 级 180 分钟

八级内容呈现明显的螺旋递进:基础语法 → 函数与算法 → 数据结构与搜索 → 动态规划与图论 → 综合与优化。

1
一级 · 编程入门
基础语法与图形编程
2
二级 · 基础拓展
存储网络知识与函数
3
三级 · 数据与算法起步
编码、数组、字符串、枚举模拟
4
四级 · 函数与算法进阶
函数、排序、递推、文件异常
5
五级 · 数论与高效算法
数论、二分、递归、分治贪心
6
六级 · 数据结构与搜索
树、搜索、背包、类、栈队列
7
七级 · 动态规划与图论
复杂DP、图、哈希
8
八级 · 综合与优化
组合、图论综合、优化

二、各级别核心能力要求总览

[['1', '一级 · 编程入门', '基础语法与图形编程', '了解计算机构成与开发环境,能独立完成简单功能的顺序、分支、循环程序'], ['2', '二级 · 基础拓展', '存储网络知识与函数', '掌握类型转换、数学库函数,能独立完成多分支与循环嵌套程序'], ['3', '三级 · 数据与算法起步', '编码、数组、字符串、枚举模拟', '掌握编码、进制、位运算,能用枚举法、模拟法解决实际问题'], ['4', '四级 · 函数与算法进阶', '函数、排序、递推、文件异常', '掌握模块化编程、递推、排序算法,理解复杂度,会文件读写'], ['5', '五级 · 数论与高效算法', '数论、二分、递归、分治贪心', '掌握数论与二分、递归、分治、贪心算法,能选择合适算法'], ['6', '六级 · 数据结构与搜索', '树、搜索、背包、类、栈队列', '掌握树与搜索算法、简单动态规划、面向对象,会使用栈队列'], ['7', '七级 · 动态规划与图论', '复杂DP、图、哈希', '掌握复杂动态规划、图论基础算法与哈希表'], ['8', '八级 · 综合与优化', '组合、图论综合、优化', '掌握组合数学、图论综合应用与算法优化']]
说明:GESP 考纲按"知识点详述 + 知识块 + 知识点描述"给出,未提供官方样题;本手册按知识点整理卡片,并以贴合考点的模拟题代替真题进行讲解。

三、使用说明与备考建议总览

  • 本手册按 GESP 8 级顺序将知识点拆分为卡片,左侧导航可快速跳转;
  • 每个知识点包含概念讲解 → 代码示例 → 易错点 → 模拟题的完整闭环,难懂处配“生活小例子”;
  • 代码块右上角有“复制”按钮,例题答案可点击“查看答案”展开;
  • 顶部可一键切换 电子学会 Python / 电子学会 C++ / GESP Python / GESP C++ 四本手册。
1

一级 · 编程入门

计算机基础 · 编程规范 · 变量与数据类型 · 顺序/分支/循环 · 输入输出 · Turtle 绘图
能力目标:了解计算机构成与开发环境,能独立完成简单功能的顺序、分支、循环程序核心:基础语法与图形编程

1.1 计算机基础与编程环境第一级知识

① 计算机的组成

  • 硬件:CPU(中央处理器,计算机的"大脑")、内存、硬盘、输入设备(键盘鼠标)、输出设备(显示器打印机);
  • 软件:操作系统(Windows、Linux、macOS)和应用软件;
  • 计算机历史:从巨大的电子管计算机发展到今天的微型机、手机、AI 电脑。

② 开发环境

Python 常用开发环境有 IDLE(自带)、PyCharmThonnyVS Code 等。GESP 一级要求会用环境新建文件、编辑、保存、运行、调试

运行方式:交互模式(>>> 逐行执行)和 脚本模式(写完整 .py 文件运行)。Python 文件后缀是 .py
易错点:① Python 用缩进表示代码块(默认 4 个空格),缩进错了会报 IndentationError;② 注释用 #

1.2 编程规范与基础语法第一级知识

① 编程规范

  • 缩进:同一代码块的行缩进必须一致;
  • 括号:成对出现(圆括号、方括号、花括号);
  • 空格与换行:运算符两边常加空格、语句之间用换行分隔;
  • 注释:# 单行注释、"""...""" 多行注释。

② 标识符、关键字、常量、变量

  • 标识符:给变量/函数起的名字,由字母、数字、下划线组成,不能以数字开头,区分大小写;
  • 关键字:Python 保留的特殊词(if、for、while、def、class 等),不能当变量名
  • 常量:值不变的数据(如 3.14"hello");
  • 变量:存数据的"箱子",可随时改值。
Python
name = "小明"      # 变量:字符串
age = 10           # 变量:整数
score = 95.5       # 变量:小数
print(name, age, score)
生活小例子:贴标签的储物箱

变量想成贴了名字的储物箱age = 10 就是往叫 age 的箱子放数字 10。

箱子有规矩:名字不能以数字开头(不能叫 2age),不能用关键字(不能叫 if),再放新东西旧东西就被换掉。

1.3 数据类型第一级知识

① 数字、字符串、布尔

类型英文例子说明
int
10-30
Python
a = 10          # int
b = 3.14        # float
c = "你好"      # str
d = True        # bool
print(type(a))  # <class 'int'>
print(type(c))  # <class 'str'>
易错点:① 字符串必须加引号,数字不加;② True/False 首字母大写;③ type() 可查看数据类型。

1.4 输入输出与运算符第一级知识

① input() 与 print()

Python
name = input("请输入名字:")   # 输入(返回字符串)
print("你好,", name)            # 输出
age = int(input("年龄:"))       # 要算数先 int()

② 算术 / 关系 / 逻辑运算符

类别符号例子结果
+ - * / %
7 // 27 % 2
31
生活小例子:邮递员送的纸条

input()邮递员:只会送来写满字的纸条。纸条上的"12"只是文字符号,要算数得先拿 int() 翻译机变成真正的数字。

不然 "12" + "5" 变成 "125"(拼接),而不是 17!口诀:要算数,先 int()。

易错点:input() 永远返回字符串;② // 整除、% 取余;③ and=并且、or=或者、not=非。

1.5 三大基本结构第一级知识

① 顺序 / 分支 / 循环

Python
# 顺序:从上到下
a = int(input()); b = int(input())
print(a + b)
# 分支
if a >= 60:
    print("及格")
else:
    print("不及格")
# 循环
s = 0
for i in range(1, 101):
    s += i
print(s)      # 5050
生活小例子:跑圈与岔路口

顺序 = 按菜谱一步一步做;分支 = 到了岔路口看条件选一条(if/else);循环 = 体育课跑圈,跑完规定的圈数(for)或跑到下课(while)。

口诀:顺序照着走、分支看条件、循环重复做。

易错点:① if 条件后要加冒号,下面缩进;② range(1, 101) 是 1~100(不含 101);③ 循环里忘记更新条件会死循环。

1.6 Turtle 绘图与模块导入第一级知识

① 模块导入

Python
import turtle          # 导入 turtle 模块
t = turtle.Turtle()   # 创建小乌龟
t.forward(100)        # 前进 100 步
t.left(90)            # 左转 90 度
t.forward(100)
turtle.done()

② Turtle 常用指令

指令作用
forward(n)/fd(n)
n
生活小例子:牵着乌龟去散步

turtle 想成一只跟着命令走的小乌龟:你说"前进 100"它就前进,说"左转 90"它就拐弯——每一条命令就像你牵着的绳子

抬笔(penup)就像把笔收起来走路不留痕迹,落笔(pendown)再画。

易错点:① 用 turtle 前必须先 import turtle;② 画完用 turtle.done() 保持窗口;③ 角度单位是度,不是步数。

一级模拟题第一级知识

以下例题贴合 GESP 一级考点(环境、变量、数据类型、运算符、结构、turtle)设计:

选择题以下哪个是合法的变量名
A. 2nameB. my-nameC. my_nameD. if
答案:C
变量名不能以数字开头(A)、不能含减号(B)、不能是关键字(D,if)。my_name 合法。
选择题int("123") + 1 的结果是?
A. "1231"B. 124C. 报错D. 123
答案:B
int("123") 把字符串转成整数 123,123 + 1 = 124。
选择题for i in range(5): 循环体会执行几次?
A. 4 次B. 5 次C. 6 次D. 无限次
答案:B
range(5) 产生 0,1,2,3,4 共 5 个数。
编程题输入一个整数,判断它是奇数还是偶数。
答案:参考程序见解析
n = int(input())
if n % 2 == 0:
    print("偶数")
else:
    print("奇数")
n % 2:余 0 是偶数,余 1 是奇数。
编程题用 turtle 画一个正方形。
答案:参考程序见解析
import turtle
t = turtle.Turtle()
for i in range(4):
    t.forward(100)
    t.left(90)
turtle.done()
正方形 = 前进 100、左转 90° 重复 4 次。
2

二级 · 基础拓展

存储与网络 · 程序设计语言 · 流程图 · ASCII · 类型转换 · 多层分支/循环 · 数学函数
能力目标:掌握类型转换、数学库函数,能独立完成多分支与循环嵌套程序核心:存储网络知识与函数

2.1 计算机存储与网络第二级知识

① 存储器的分类

存储器特点用途
RAM

② 计算机网络

  • 网络分类:局域网 LAN(一间教室)、城域网 MAN(一座城市)、广域网 WAN(全世界,如互联网);
  • TCP/IP 四层模型:应用层、传输层、网络层、网络接口层;
  • IP 地址:网络中每台设备的"门牌号"(如 192.168.1.1)。
生活小例子:书桌、保险箱和速记本

把存储器想成你的学习工具RAM 是书桌(写作业时摊开的本子,放学收走就没了=断电丢失);ROM 是保险箱(里面放着不会变的说明书=开机程序);Cache 是手边的速记本(最常用公式抄在上面,拿起来最快)。

易错点:① RAM 断电丢失,ROM 断电不丢;② 互联网是全世界最大的广域网;③ 每个联网设备都有唯一 IP 地址。

2.2 程序设计语言与流程图第二级知识

① 程序设计语言分类

语言特点例子
0/1
0100 1011

② 流程图

流程图用图形描述算法步骤:圆角矩形=开始/结束、平行四边形=输入输出、矩形=处理、菱形=判断、箭头=流程方向。

易错点:① 高级语言需要翻译(编译/解释)成机器语言才能执行;② 流程图判断用菱形;③ Python 属于解释型高级语言。

2.3 ASCII 编码第二级知识

① ASCII 码

ASCII 用数字表示字符,是最基础的字符编码。需要记住几个关键值:

字符ASCII 码
32
Python
print(ord("A"))    # 65(字符转编码)
print(chr(65))    # 'A'(编码转字符)
# 小写 = 大写 + 32:'a' = 65 + 32 = 97
print(ord("a") - ord("A"))   # 32
易错点:ord() 字符→数字,chr() 数字→字符;② 数字'0'的编码是 48,字母'A'是 65,'a'是 97;③ 小写字母比大写字母大 32。

2.4 数据类型转换第二级知识

① 强制转换与隐式转换

Python
x = int("123")       # 字符串→整数
y = float("3.5")     # →小数
s = str(100)         # 整数→字符串
n = int(3.99)        # 3(截断,不是四舍五入)
print(round(3.6))    # 4(四舍五入)
# 隐式转换:int 和小数运算自动变成小数
print(3 + 0.5)       # 3.5
易错点:int("12.5")报错(不是整数格式);② int(3.99) 是截断成 3;③ 字符和数字通过 ord/chr 互相转换。

2.5 多层分支与多层循环第二级知识

① 多层分支(elif)

Python
score = int(input())
if score >= 90:
    print("优秀")
elif score >= 80:
    print("良好")
elif score >= 60:
    print("及格")
else:
    print("不及格")

② 多层循环(嵌套)

Python
for i in range(1, 6):        # 外层管行
    for j in range(1, i + 1):   # 内层管列
        print("*", end="")
    print()                     # 换行
# 输出直角三角形
易错点:① elif 命中后跳过后面;② 嵌套循环总次数 = 外层 × 内层;③ 打印图形每行记得换行。

2.6 数学函数第二级知识

① 常用数学函数

Python
import math
abs(-5)          # 5    绝对值
max(3, 7, 2)     # 7    最大值
min(3, 7, 2)     # 2    最小值
round(3.6)       # 4    四舍五入
math.sqrt(25)    # 5.0  平方根
pow(2, 10)       # 1024 乘方
# 随机数
import random
random.randint(1, 6)   # 1~6 随机整数(掷骰子)
易错点:① 平方根要用 math.sqrt,需先 import math;② random.randint(a, b) 包含两端;③ round() 四舍五入。

二级模拟题第二级知识

选择题以下哪种存储器断电后数据会丢失?
A. ROMB. RAMC. 光盘D. 硬盘
答案:B
RAM(内存)断电丢失;ROM、光盘、硬盘断电不丢。
选择题字符 "a" 的 ASCII 码是?
A. 65B. 97C. 48D. 32
答案:B
A=65,a=97,小写比大写大 32。
选择题int(3.99) 的结果是?
A. 4B. 3C. 3.99D. 报错
答案:B
int() 转换是截断,去掉小数部分得 3。
编程题用嵌套循环打印九九乘法表。
答案:参考程序见解析
for i in range(1, 10):
    for j in range(1, i + 1):
        print(f"{j}*{i}={i*j}", end="\t")
    print()
外层 i 是乘数,内层 j 从 1 到 i。
3

三级 · 数据与算法起步

数据编码 · 进制转换 · 位运算 · 算法描述 · 数组/容器 · 字符串 · 枚举法 · 模拟法
能力目标:掌握编码、进制、位运算,能用枚举法、模拟法解决实际问题核心:编码、数组、字符串、枚举模拟

3.1 数据编码:原码、反码、补码第三级知识

① 三种编码

计算机用二进制存整数,负数有原码、反码、补码三种表示:

编码正数负数说明
1 +
0 1

例:8 位二进制表示 -3:原码 10000011,反码 11111100,补码 11111101

易错点:① 计算机统一用补码存储和计算负数;② 正数三种编码一样;③ ~x = -x - 1(按位取反)。

3.2 进制转换第三级知识

① 常见进制

进制基数数字例子
2
0 1
1010 = 10

② 十进制转二进制(除 2 取余)

Python
n = 13
s = ""
while n > 0:
    s = str(n % 2) + s    # 余数往前拼
    n //= 2
print(s)                  # 1101
# Python 内置
print(bin(13))    # 0b1101
print(hex(255))   # 0xff
print(int("1101", 2))   # 13
生活小例子:4 盏灯的开关

二进制想成4 盏灯(亮=1 灭=0),分量从左到右是 8、4、2、1:想表示 13 就亮"8+4+1"三盏 → 1101。电脑里所有数据都是灯的亮灭!

易错点:① 除 2 取余要倒着写余数;② 十六进制 A~F 表示 10~15;③ bin/oct/hex 输出带前缀。

3.3 位运算第三级知识

① 位运算符

符号含义例子结果
&
5 & 3
1
Python
n = 7
print(n & 1)      # 1 → 奇数(判断奇偶)
print(n << 1)     # 14(×2)
print(n >> 1)     # 3(÷2)
a, b = 5, 3
a ^= b; b ^= a; a ^= b   # 交换两数(异或技巧)
易错点:& 1 判奇偶;② 左移一位 = ×2、右移一位 = ÷2;③ 位运算优先级低,判断时要加括号 (n & 1)

3.4 算法的概念与描述第三级知识

① 什么是算法

算法就是解决问题的一步步明确步骤。三种描述方式:

  • 自然语言:用日常话描述("先输入,再计算,最后输出");
  • 流程图:用图形表示流程(菱形=判断、矩形=处理);
  • 伪代码:像代码但更随意,不要求能运行。
输入数据处理(计算/判断)输出结果
易错点:① 算法必须有穷(不能无限循环)、明确(每步无歧义)、可行;② 三种描述本质表达同一件事。

3.5 Python 数据结构:列表/字典/元组/集合第三级知识

① 四种内置容器

类型符号特点例子
list
[ ]
[1, 2, 3]

② 常用操作与列表解析

Python
lst = [3, 1, 2]
lst.append(5)          # 末尾加
lst.sort()             # 排序
lst[0]                 # 第一个元素
# 列表解析(推导式)
squares = [x * x for x in range(5)]    # [0,1,4,9,16]
even = [x for x in range(10) if x % 2 == 0]   # 偶数
d = {"name": "小明", "age": 10}
d["name"]              # "小明"
s = {1, 2, 2, 3}       # {1, 2, 3}(去重)
生活小例子:储物柜、通讯录和布袋

列表=一排编号储物柜(按位置取);字典=通讯录(按名字找电话);集合=布袋(重复的东西只留一个);列表解析=加工厂流水线(一批原料一次加工成产品)。

易错点:① 列表下标从 0 开始;② 字典按键访问,键必须唯一;③ 列表解析格式:[表达式 for 变量 in 序列 if 条件]

3.6 字符串及其函数第三级知识

① 字符串函数

函数作用例子结果
upper()/lower()
"Hi".lower()
"hi"
Python
s = "Python Programming"
print(s.upper())         # PYTHON PROGRAMMING
print(s.split(" "))      # ['Python', 'Programming']
print(s[0:6])            # 'Python'(切片)
易错点:① 字符串不可变(方法返回新串);② 切片含头不含尾;③ split 按分隔符拆成列表、join 反向拼回。

3.7 枚举法第三级知识

① 枚举法

Python
# 找 100~999 的水仙花数
for n in range(100, 1000):
    a = n // 100
    b = n // 10 % 10
    c = n % 10
    if a**3 + b**3 + c**3 == n:
        print(n, end=" ")    # 153 370 371 407
生活小例子:翻遍抽屉找钥匙

枚举想成钥匙不见了,挨个抽屉翻:从第一个翻到最后一个,不重不漏,翻到就验证。循环是"挨个抽屉",if 是"看看是不是钥匙"。

易错点:① 枚举范围要完整判断条件要正确;② 数据很大时枚举太慢,要换算法。

3.8 模拟法第三级知识

① 模拟法

Python
# 模拟:每天存钱,第 1 天 1 元、第 2 天 2 元……n 天后共多少
n = 10
total = 0
for day in range(1, n + 1):
    total += day
print(total)      # 55
生活小例子:照说明书做实验

模拟法想成照着说明书一步步做实验:说明书写"第一步加 1 滴,第二步加 2 滴…",你就一步一步照做。题目怎么说,代码就怎么写,别自作聪明跳步。

易错点:① 模拟的关键是读懂题意、把过程原样实现;② 注意循环次数和边界,错一步整题错。

三级模拟题第三级知识

选择题-5 的 8 位补码是?
A. 10000101B. 11111011C. 11111010D. 00000101
答案:B
-5 原码 10000101,反码 11111010(符号位不变取反),补码 = 反码+1 = 11111011。
选择题十进制 13 转二进制是?
A. 1010B. 1101C. 1110D. 1001
答案:B
13 = 8+4+1 → 1101。
选择题[x for x in range(6) if x % 2 == 1] 的结果是?
A. [0,2,4]B. [1,3,5]C. [1,2,3]D. [0,1,2,3,4,5]
答案:B
列表解析:x 取 0~5,保留奇数 → [1,3,5]。
编程题用枚举法找出 100~999 中所有"回文数"(如 121)。
答案:参考程序见解析
for n in range(100, 1000):
    if n // 100 == n % 10:
        print(n)
三位数回文:百位 == 个位。
4

四级 · 函数与算法进阶

函数 · 作用域 · 参数传递 · 复合类型嵌套 · 递推 · 排序 · 复杂度 · 文件 · 异常
能力目标:掌握模块化编程、递推、排序算法,理解复杂度,会文件读写核心:函数、排序、递推、文件异常

4.1 函数:定义、调用与参数第四级知识

① 函数的定义与调用

Python
def add(a, b):        # a、b 是形参
    return a + b
result = add(3, 5)    # 3、5 是实参
print(result)         # 8

② 形参 vs 实参

  • 形参:函数定义时的"占位符"(菜谱里的"适量");
  • 实参:调用时真正传入的值(做菜时放的实际用量);
  • 默认参数:没传时用默认值 def f(x, n=2):
生活小例子:妈妈的拿手菜谱

函数想成菜谱:写好一次随时照着做。形参=菜谱写的"放几个蛋",实参=你实际放 3 个蛋,return=端上桌的菜。一次写好,反复使用!

易错点:① 有返回值要 return;② return 之后的代码不执行;③ 函数要先定义再调用。

4.2 作用域与参数传递第四级知识

① 全局 vs 局部

Python
x = 10                # 全局变量
def f():
    x = 20            # 局部变量(函数内新造一个)
    print(x)          # 20
f()
print(x)              # 10(外面没变)

② 修改全局要用 global

Python
count = 0
def add():
    global count      # 声明要用全局的 count
    count += 1
add(); add()
print(count)          # 2

③ Python 参数传递

  • 不可变类型(int、str、元组):按传递,函数内改不影响外面;
  • 可变类型(列表、字典):按引用传递,函数内修改会影响外面。
Python
def change(lst):
    lst.append(99)      # 列表可变,外面也会变
a = [1, 2]
change(a)
print(a)              # [1, 2, 99]
易错点:① 函数内赋值默认创建局部变量;② 想改全局要 global 声明;③ 列表/字典传引用,改了影响外面。

4.3 复合数据类型嵌套第四级知识

① 嵌套使用

Python
# 列表里套字典(学生表)
students = [
    {"name": "小明", "scores": [90, 85]},
    {"name": "小红", "scores": [88, 95]},
]
print(students[0]["name"])        # 小明
print(students[1]["scores"][0])   # 88
# 字典里套列表
scores = {"math": [80, 90], "chinese": [85, 92]}
for k, v in scores.items():
    print(k, sum(v) / len(v))
易错点:① 从外到内逐层用下标/键访问;② 常用 for k, v in d.items() 遍历字典;③ 二维列表 a[i][j] 表示第 i 行第 j 列。

4.4 递推算法第四级知识

① 递推的思想

从已知的初始项出发,用循环从前往后一步步推出后面的项。

Python
# 斐波那契:f(1)=1, f(2)=1, f(n)=f(n-1)+f(n-2)
n = 10
f = [0] * (n + 1)
f[1] = f[2] = 1
for i in range(3, n + 1):
    f[i] = f[i - 1] + f[i - 2]
print(f[n])       # 55
生活小例子:爬楼梯

到第 n 级台阶,只能从 n-1 走 1 步或从 n-2 走 2 步,所以 f(n)=f(n-1)+f(n-2)。先算小的,一步步推大的,就是递推!

易错点:① 先定初始值;② 递推比递归快(不重复计算);③ 大数注意用 Python 内置大整数(Python 不会溢出)。

4.5 排序算法与稳定性第四级知识

① 冒泡排序

Python
def bubble(a):
    n = len(a)
    for i in range(n - 1):
        for j in range(n - 1 - i):
            if a[j] > a[j + 1]:
                a[j], a[j + 1] = a[j + 1], a[j]
    return a

② 插入排序 / 选择排序

Python
def insert_sort(a):
    for i in range(1, len(a)):
        key = a[i]; j = i - 1
        while j >= 0 and a[j] > key:
            a[j + 1] = a[j]; j -= 1
        a[j + 1] = key
    return a

def select_sort(a):
    for i in range(len(a) - 1):
        mn = i
        for j in range(i + 1, len(a)):
            if a[j] < a[mn]: mn = j
        a[i], a[mn] = a[mn], a[i]
    return a

③ 稳定性

稳定排序:相等元素排序后相对顺序不变。冒泡、插入稳定;选择不稳定

生活小例子:三种排队法

冒泡=相邻比个子高的往后挪,一轮沉底一个;选择=每轮挑最矮的站前面;插入=打扑克抓一张插到已排好牌中合适位置。

易错点:① 三种排序都是 O(n²);② 稳定排序=相等的元素顺序不乱;③ 冒泡和插入稳定,选择不稳定。

4.6 算法复杂度估算第四级知识

① 时间复杂度的概念

时间复杂度描述数据规模 n 变大时,运算次数增长的快慢

代码结构复杂度
O(1)
a = 1
易错点:① 一层循环 O(n)、两层 O(n²);② 只保留最高次项(n²+n 记作 O(n²));③ 指数复杂度增长极快,n 稍大就跑不动。

4.7 文件读写与异常处理第四级知识

① 文件读写

Python
# 写文件
with open("out.txt", "w", encoding="utf-8") as f:
    f.write("第一行\n")
# 追加
with open("out.txt", "a", encoding="utf-8") as f:
    f.write("追加内容\n")
# 读文件
with open("out.txt", "r", encoding="utf-8") as f:
    for line in f:
        print(line.strip())

② 异常处理 try-except

Python
try:
    n = int(input("请输入整数:"))
    print(100 // n)
except ValueError:
    print("输入的不是整数!")
except ZeroDivisionError:
    print("不能除以 0!")
易错点:① "w" 会覆盖,追加用 "a";② with open 自动关闭文件;③ try 里出错会跳到 except,程序不崩溃。

四级模拟题第四级知识

选择题以下哪个函数能修改函数外的列表?
A. 传整数B. 传字符串C. 传列表D. 传元组
答案:C
列表是可变类型按引用传递,函数内修改会影响外面;int/str/元组不可变,改了不影响。
选择题冒泡排序和插入排序是稳定排序,选择排序是?
A. 稳定B. 不稳定C. 都是D. 无法判断
答案:B
选择排序可能交换相等元素的位置,是不稳定排序。
选择题双层循环(每层 n 次)的时间复杂度是?
A. O(1)B. O(n)C. O(n²)D. O(2ⁿ)
答案:C
两层嵌套 n×n 次 → O(n²)。
编程题用递推求第 n 个斐波那契数。
答案:参考程序见解析
f=[0]*(n+1); f[1]=f[2]=1
for i in range(3,n+1): f[i]=f[i-1]+f[i-2]
print(f[n])
从 f[1]、f[2] 出发循环递推。
编程题读取一个文件里的所有数字并求和。
答案:参考思路见解析
with open("a.txt") as f:
    total = sum(int(line.strip()) for line in f)
print(total)
逐行读取、转 int、累加。
5

五级 · 数论与高效算法

初等数论 · 高精度 · 链表 · 筛法 · 二分 · 递归 · 分治 · 贪心
能力目标:掌握数论与二分、递归、分治、贪心算法,能选择合适算法核心:数论、二分、递归、分治贪心

5.1 初等数论第五级知识

① 素数与合数、约数与倍数

Python
def is_prime(n):
    if n < 2: return False
    i = 2
    while i * i <= n:
        if n % i == 0: return False
        i += 1
    return True

② 最大公约数与最小公倍数

Python
def gcd(a, b):          # 辗转相除法(欧几里得)
    while b:
        a, b = b, a % b
    return a
def lcm(a, b):
    return a * b // gcd(a, b)

③ 同余与模运算

  • a % b 表示 a 除以 b 的余数(7 % 3 = 1);
  • 模运算性质:(a+b) % m = (a%m + b%m) % m
  • 质因数分解:把数拆成质数相乘,如 12 = 2×2×3。
生活小例子:铺地砖找最大块

要铺 24×36 的墙,最大公约数就是能同时整除两边的最大的砖:12。辗转相除法就像大砖切小砖——36 切 24 剩 12,24 再切 12 刚好,答案 12。

易错点:① 判断素数只需试到 √n;② gcd 用辗转相除法,lcm = a×b÷gcd;③ Python 内置 math.gcd

5.2 算法复杂度估算第五级知识

① 各种复杂度

复杂度n=10⁶ 时典型算法
O(1)
易错点:对数复杂度 O(log n) 出现于二分/倍增;② 排序 O(n log n) 比 O(n²) 快很多;③ 估算时只关心最高次项和增长趋势。

5.3 二分查找与二分答案第五级知识

① 二分查找(有序数组)

Python
def binary_search(a, x):
    l, r = 0, len(a) - 1
    while l <= r:
        mid = (l + r) // 2
        if a[mid] == x: return mid
        elif a[mid] < x: l = mid + 1
        else: r = mid - 1
    return -1

② 二分答案(猜答案)

Python
# 例:把 n 根长度不一的绳子切成 m 段,求每段最长能多长
def ok(mid, a, m):
    return sum(x // mid for x in a) >= m

n, m = 3, 4
a = [10, 15, 7]          # 绳子长度
l, r = 1, max(a)
while l <= r:
    mid = (l + r) // 2
    if ok(mid, a, m): l = mid + 1
    else: r = mid - 1
print(r)                 # 最长能切 5
生活小例子:翻字典猜页数

猜字典里某个字在第几页:翻到中间,比目标大就往左半本找,小就往右半本找,每次都砍掉一半——这就是二分。100 万个数最多 20 次就找到!

易错点:① 二分前提是有序(或具有单调性);② 每次 mid=(l+r)//2;③ 二分答案:先判断"答案够不够大"再收窄区间。

5.4 递归算法第五级知识

① 递归 = 自己调自己

Python
def fact(n):
    if n <= 1: return 1        # 终止条件(非常重要)
    return n * fact(n - 1)     # 递归调用

② 递归的时空复杂度与优化

  • 递归必须有终止条件,否则无限递归(Python 默认限制约 1000 层);
  • 朴素递归斐波那契是 O(2ⁿ),指数爆炸;
  • 优化:记忆化(缓存算过的结果)或改用递推。
Python
from functools import lru_cache
@lru_cache(maxsize=None)
def fib(n):
    if n <= 2: return 1
    return fib(n - 1) + fib(n - 2)
print(fib(50))    # 12586269025(很快)
生活小例子:套娃与传话

递归就像俄罗斯套娃:打开大娃得到小娃,再打开小娃得到更小的……直到最小的(终止条件),再一层层带回答案。先一路拆到底,再一路算上来。

易错点:① 递归 = 递推关系 + 终止条件;② 记忆化把 O(2ⁿ) 变成 O(n);③ 尾递归/递推可避免栈溢出。

5.5 分治算法:归并与快排第五级知识

① 归并排序(先拆后合)

Python
def merge_sort(a):
    if len(a) <= 1: return a
    m = len(a) // 2
    L = merge_sort(a[:m]); R = merge_sort(a[m:])
    i = j = 0; res = []
    while i < len(L) and j < len(R):
        if L[i] < R[j]: res.append(L[i]); i += 1
        else: res.append(R[j]); j += 1
    return res + L[i:] + R[j:]

② 快速排序(选基准,分两边)

Python
def quick_sort(a):
    if len(a) <= 1: return a
    p = a[0]
    less = [x for x in a[1:] if x <= p]
    more = [x for x in a[1:] if x > p]
    return quick_sort(less) + [p] + quick_sort(more)
生活小例子:全班按身高排队

归并=先把全班分成两组各自排好,再把两组按顺序合并成一队;快排=随便叫一个同学当"基准",矮的站左边高的站右边,两边再各自排——分而治之!

易错点:① 分治三步:分解→解决→合并;② 归并、快排平均 O(n log n);③ 归并稳定、快排不稳定。

5.6 贪心算法第五级知识

① 贪心的思想

每一步都选当前看起来最优的选择,最终得到全局最优。贪心要满足最优子结构(局部最优能推出全局最优)。

Python
# 例:硬币找零(面额 1/5/10/20/50,求最少硬币数)
coins = [50, 20, 10, 5, 1]
amount = 78
count = 0
for c in coins:
    count += amount // c
    amount %= c
print(count)     # 5(50+20+5+1+1+1=6? 实际 78=50+20+5+1+1+1)

上例 78 = 50+20+5+1+1+1,共 6 枚。贪心每次先用大面额,是最优的。

生活小例子:每次挑最大的苹果

贪心想成每次从篮子里挑最大的苹果:每次都选当前最好,凑到一起往往就是最好的一篮。但要注意:有些问题"每次挑最大的"反而错,要先验证最优子结构!

易错点:① 贪心要证明局部最优 = 全局最优;② 反例:硬币面额不是倍数关系时贪心可能失败;③ 适合区间调度、找零(特定面额)、部分背包等。

五级模拟题第五级知识

选择题辗转相除法求 gcd(48, 36) 的结果是?
A. 6B. 12C. 18D. 24
答案:B
48%36=12,36%12=0 → gcd=12。
选择题在有序数组里做二分查找,查找 n 个元素最多比较几次?
A. n 次B. n/2 次C. ⌈log₂n⌉+1 次D. 1 次
答案:C
每次砍半,最多约 log₂n+1 次比较。
选择题归并排序的时间复杂度是?
A. O(n)B. O(n²)C. O(n log n)D. O(log n)
答案:C
归并排序是分治,稳定,平均与最坏都是 O(n log n)。
编程题给定 n 个数,用二分查找某个数是否存在。
答案:参考思路见解析
a.sort()
l,r=0,len(a)-1
while l<=r:
    m=(l+r)//2
    if a[m]==x: print("YES"); break
    elif a[m]<x: l=m+1
    else: r=m-1
else: print("NO")
先排序再二分。
编程题判断 n 是否为素数(n≤10⁹)。
答案:参考程序见解析
i=2; ok=True
while i*i<=n:
    if n%i==0: ok=False; break
    i+=1
print("YES" if ok and n>1 else "NO")
只需试到 √n。
6

六级 · 数据结构与搜索

树 · 哈夫曼 · 完全二叉树 · 二叉排序树 · DFS/BFS · 简单DP/背包 · 面向对象 · 栈队列
能力目标:掌握树与搜索算法、简单动态规划、面向对象,会使用栈队列核心:树、搜索、背包、类、栈队列

6.1 树的基本概念与遍历第六级知识

① 树的定义

  • 树:n 个结点组成的分层结构,有且只有一个,每个结点有 0 个或多个孩子
  • 常用词:根、父结点、子结点、叶子(没孩子的)、深度(层数)。

② 二叉树的遍历

Python
class Node:
    def __init__(self, v):
        self.v = v; self.left = None; self.right = None

def preorder(r):          # 前序:根-左-右
    if not r: return
    print(r.v, end=" "); preorder(r.left); preorder(r.right)
def inorder(r):           # 中序:左-根-右
    if not r: return
    inorder(r.left); print(r.v, end=" "); inorder(r.right)
def postorder(r):         # 后序:左-右-根
    if not r: return
    postorder(r.left); postorder(r.right); print(r.v, end=" ")
生活小例子:家族族谱

想成族谱:爷爷是根,下面分爸爸、叔叔(孩子),再往下孙子。前序=先记自己再往下记(根左右),中序=先左再自己再右,后序=先孩子最后自己。

易错点:① 一棵树只有一个根;② 叶子结点没有孩子;③ 三种遍历的区别是"根"出现的位置。

6.2 哈夫曼树与编码第六级知识

① 哈夫曼树(最优二叉树)

给定一组权值(出现频率),构造带权路径长度最小的二叉树。构造方法:每次选两个最小的合并

选权值最小的两个结点合并成新结点(权值=两者之和)重复直到只剩一棵树

② 哈夫曼编码

左 0 右 1 给每个叶子标路径,频率越高的字符路径越短。特点是前缀编码(任何编码都不是另一个的前缀),可无歧义解码。

易错点:① 每次挑两个最小的合并;② 叶子数 n,结点总数 2n-1;③ 高频字符编码短 → 压缩率更高。

6.3 完全二叉树与二叉排序树第六级知识

① 完全二叉树

除最后一层外都填满,最后一层结点靠左排列。完全二叉树可用数组存储:下标 i 的左孩子 2i、右孩子 2i+1、父亲 i//2。

② 二叉排序树(BST)

Python
def insert(root, x):
    if root is None: return Node(x)
    if x < root.v: root.left = insert(root.left, x)
    else: root.right = insert(root.right, x)
    return root
# 中序遍历 BST = 从小到大输出
生活小例子:图书馆按编号插书

二叉排序树=图书馆书架:比编号小的放左边,大的放右边。中序遍历就是从左到右把书按编号排好——插入时一路比较,位置合适就停下。

易错点:① 完全二叉树用数组存,下标规律要记牢;② BST 中序遍历有序;③ BST 退化成链会变 O(n),要平衡。

6.4 深度优先搜索 DFS第六级知识

① DFS 思想

Python
def dfs(x):
    if 越界 or 访问过: return
    visited[x] = True
    print(x, end=" ")
    for nxt in 邻居[x]:
        dfs(nxt)

DFS 像走进迷宫:一条路走到黑,走不通再回头换一条。

生活小例子:迷宫探路

DFS=迷宫探险家一条道走到黑,撞墙就回头(回溯)走另一条,走过的路做记号(visited)防止绕圈。

易错点:① DFS 用递归或栈实现;② 必须有 visited 防止死循环;③ 适合找所有路径、全排列、连通块。

6.5 广度优先搜索 BFS第六级知识

① BFS 思想

Python
from collections import deque
def bfs(start):
    q = deque([start])
    visited = {start}
    while q:
        x = q.popleft()
        print(x, end=" ")
        for nxt in 邻居[x]:
            if nxt not in visited:
                visited.add(nxt); q.append(nxt)
生活小例子:水波一圈圈扩散

BFS=往池塘扔石子,水波一圈圈向外扩散:先到的地方离起点最近。用队列(先来先出)实现,先到的先扩展。找最短步数最合适。

易错点:① BFS 用队列、DFS 用递归/栈;② BFS 第一次到达 = 最短距离(无权图);③ 入队时标记 visited。

6.6 简单动态规划第六级知识

① 一维 DP:爬楼梯

Python
n = 10
dp = [0] * (n + 1)
dp[0] = 1
for i in range(1, n + 1):
    dp[i] = dp[i - 1] + (dp[i - 2] if i >= 2 else 0)
print(dp[n])   # 89

② 简单背包(0-1 背包)

Python
# 背包容量 W,物品重量 w、价值 v,求最大价值
W, n = 10, 3
w = [0, 3, 4, 5]; v = [0, 4, 5, 6]
dp = [0] * (W + 1)
for i in range(1, n + 1):
    for j in range(W, w[i] - 1, -1):   # 倒序!0-1 背包
        dp[j] = max(dp[j], dp[j - w[i]] + v[i])
print(dp[W])   # 10
生活小例子:出游装箱

0-1 背包=带 10kg 的箱子出门,每个物品只能带一个或不带,怎么装最值钱?dp[j]=箱子容量 j 时能装的最大价值,逐个物品更新。倒序循环保证每个物品只用一次!

易错点:① 动态规划 = 状态 + 转移方程 + 初始值;② 0-1 背包容量倒序、完全背包正序;③ 先想清楚 dp[i] 表示什么。

6.7 面向对象:类第六级知识

① 类与对象

Python
class Dog:
    def __init__(self, name, age):   # 构造方法
        self.name = name             # 属性
        self.age = age
    def bark(self):                  # 方法
        print(self.name, "汪汪!")
d = Dog("旺财", 3)
d.bark()    # 旺财 汪汪!

② 三大特性

  • 封装:把数据和操作包在类里,外界通过方法访问;
  • 继承:子类继承父类的属性和方法,可以扩展;
  • 多态:同一操作在不同对象上有不同表现。
生活小例子:做蛋糕的模具

=做饼干的模具(模板),对象=用模具压出的每一块饼干。__init__=给每块饼干印上不同花纹。继承=大模具分出小模具,多态=同样的模具印出不同形状。

易错点:self 代表对象本身,方法都要有它;② 类首字母大写是习惯;③ 三大特性:封装、继承、多态。

6.8 栈、队列、循环队列第六级知识

① 栈 Stack(后进先出)

Python
from collections import deque
s = deque()          # 用双端队列当栈
s.append(1); s.append(2)
print(s.pop())       # 2(后进先出)

② 队列 Queue(先进先出)

Python
q = deque()
q.append(1); q.append(2)
print(q.popleft())   # 1(先进先出)

循环队列:用数组实现时,队尾到头再绕回队首,解决假溢出。

生活小例子:叠盘子与排队

=食堂叠盘子:后放的先拿(后进先出);队列=排队打饭:先来的先走(先进先出)。

易错点:① 栈:后进先出(LIFO);② 队列:先进先出(FIFO);③ Python 用 collections.deque 实现两者。

六级模拟题第六级知识

选择题二叉树前序遍历顺序是?
A. 左-根-右B. 根-左-右C. 左-右-根D. 根-右-左
答案:B
前序=根左右,中序=左根右,后序=左右根。
选择题0-1 背包的容量循环必须?
A. 正序B. 倒序C. 任意D. 每次 +2
答案:B
0-1 背包倒序保证每个物品只取一次;完全背包才用正序。
选择题BFS 用哪种数据结构实现?
A. 栈B. 队列C. 堆D. 集合
答案:B
BFS 用队列(先进先出),DFS 用递归或栈。
编程题用 BFS 求迷宫从起点到终点的最少步数。
答案:参考思路见解析
q=deque([(sx,sy,0)])
while q:
    x,y,step=q.popleft()
    if (x,y)==(tx,ty): print(step); break
    for dx,dy in [(1,0),(-1,0),(0,1),(0,-1)]:
        nx,ny=x+dx,y+dy
        if 在界内且可走且未访问:
            标记访问; q.append((nx,ny,step+1))
每步记录步数,第一次到达终点的步数即最短。
编程题创建 Student 类含姓名和分数,并能输出。
答案:参考程序见解析
class Student:
    def __init__(self, name, score):
        self.name=name; self.score=score
    def show(self):
        print(self.name, self.score)
构造方法存属性,方法输出。
7

七级 · 动态规划与图论

数学库函数 · 复杂DP · 图的定义与遍历 · flood fill · 哈希表
能力目标:掌握复杂动态规划、图论基础算法与哈希表核心:复杂DP、图、哈希

7.1 数学库常用函数第七级知识

① 三角 / 对数 / 指数

Python
import math
math.sin(math.pi / 2)    # 1.0  正弦(弧度)
math.cos(0)              # 1.0  余弦
math.log10(1000)         # 3.0  以 10 为底的对数
math.log2(8)             # 3.0  以 2 为底
math.exp(1)              # e ≈ 2.718
math.pow(2, 10)          # 1024.0
易错点:① 三角函数参数是弧度不是角度;② log10 以 10 为底、log2 以 2 为底;③ exp(x) = eˣ。

7.2 复杂动态规划第七级知识

① 最长上升子序列 LIS

Python
a = [3, 1, 4, 1, 5, 9, 2, 6]
n = len(a)
dp = [1] * n
for i in range(n):
    for j in range(i):
        if a[j] < a[i]:
            dp[i] = max(dp[i], dp[j] + 1)
print(max(dp))    # 4(1,4,5,9 或 1,4,5,6)

② 最长公共子序列 LCS

Python
s1, s2 = "abcde", "ace"
m, n = len(s1), len(s2)
dp = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(1, m + 1):
    for j in range(1, n + 1):
        if s1[i-1] == s2[j-1]:
            dp[i][j] = dp[i-1][j-1] + 1
        else:
            dp[i][j] = max(dp[i-1][j], dp[i][j-1])
print(dp[m][n])   # 3("ace")

③ 区间 DP 与滚动数组

  • 区间 DP:状态是"区间 [i,j]",如石子合并;
  • 滚动数组:DP 只依赖上一行,用两行(甚至两列)滚动省内存,把 O(n²) 空间降到 O(n)。
易错点:① LIS:dp[i]=以 a[i] 结尾的最长上升序列长度;② LCS 用二维 DP;③ 滚动数组 = 只保留需要的行,大幅省空间。

7.3 图的定义与遍历第七级知识

① 图的定义

  • 图 = 顶点(结点)+ 边(连接关系);
  • 按方向分:有向图(单行路)、无向图(双行路);
  • 顶点的 = 连接的边数(无向图);有向图分入度/出度

② 图的存储与遍历

Python
# 邻接表存图
graph = [[] for _ in range(n + 1)]
# 加一条 u→v 的边
graph[u].append(v)

def dfs(u):
    visited[u] = True
    for v in graph[u]:
        if not visited[v]:
            dfs(v)
易错点:① 邻接表:每个点挂一个邻居列表,省空间;② DFS/BFS 都能遍历图,加 visited 防重复;③ 有向图边有方向,遍历只走指向方向。

7.4 图的泛洪算法 flood fill第七级知识

① 连通块计数

Python
# 数一个 0/1 地图上有几块 1 的连通块
def flood_fill(x, y):
    stack = [(x, y)]; a[x][y] = 0
    while stack:
        i, j = stack.pop()
        for dx, dy in [(1,0),(-1,0),(0,1),(0,-1)]:
            ni, nj = i + dx, j + dy
            if 0 <= ni < n and 0 <= nj < m and a[ni][nj] == 1:
                a[ni][nj] = 0; stack.append((ni, nj))

cnt = 0
for i in range(n):
    for j in range(m):
        if a[i][j] == 1:
            cnt += 1
            flood_fill(i, j)
print(cnt)
生活小例子:给孤岛编号

flood fill=看一张小岛地图,从一块陆地出发把相连的整片都染色(访问过=淹掉),一块块数出共有几座岛。DFS 或 BFS 都行,关键是"整片一起处理"。

易错点:① 连通块 = 相互可达的点集;② 访问过的格子要标记,否则重复计数;③ 四方向/八方向按题意选。

7.5 哈希表第七级知识

① 哈希的思想

哈希函数把"键"映射到一个位置(下标),实现 O(1) 的查找/插入/删除。Python 的 dict 和 set 底层就是哈希表

Python
d = {}
d["apple"] = 3          # 插入/更新
print(d.get("apple"))   # 3(O(1) 查找)
s = {1, 2, 3}
print(1 in s)           # True(O(1) 判断存在)
生活小例子:按首字母分格的储物架

哈希表想成按首字母分格子的储物架:找"apple"直接去 A 格拿,不用一格一格翻——这就是哈希函数帮你算好位置。冲突=两个词撞进同一格,用"链子"串起来。

易错点:① 哈希表平均 O(1),但要处理冲突;② 有序遍历需求请用 list/排序(哈希无序);③ Python dict/set 就是哈希。

七级模拟题第七级知识

选择题math.log2(16) 的值是?
A. 2B. 4C. 8D. 16
答案:B
2⁴=16,所以 log2(16)=4。
选择题LIS 问题中 dp[i] 通常表示?
A. 前 i 个数的和B. 以 a[i] 结尾的最长上升子序列长度C. 全局最长D. 数组长度
答案:B
经典定义:dp[i]=以 a[i] 结尾的 LIS 长度。
选择题无向图中顶点 v 的度是?
A. 指向 v 的边数B. 从 v 出发的边数C. 与 v 相连的边数D. 顶点个数
答案:C
无向图的度=相连边数;有向图才分入度/出度。
编程题用哈希表统计字符串中每个字符出现次数。
答案:参考程序见解析
d={}
for ch in s:
    d[ch]=d.get(ch,0)+1
d.get(ch,0) 取不到返回 0,加 1 计数。
8

八级 · 综合与优化

计数原理 · 排列组合 · 杨辉三角 · 倍增 · 代数几何 · 最小生成树 · 最短路 · 时空分析
能力目标:掌握组合数学、图论综合应用与算法优化核心:组合、图论综合、优化

8.1 计数原理:加法与乘法第八级知识

① 加法原理 / 乘法原理

  • 加法原理:做一件事有 m 种方法 n 种方法(分类,互斥)→ m+n;
  • 乘法原理:做一件事分两步,第一步 m 种、第二步 n 种(分步,连续)→ m×n。
生活小例子:点餐的两种算法

套餐 A 或 B 任选一个=加法(2 种);主食+饮料各选一个=乘法(3 主食×2 饮料=6 种)。加"或"、乘"和"——分类相加、分步相乘!

易错点:① 关键词"或"→加法,"再/然后"→乘法;② 分类不能重叠(互斥);③ 分步之间要独立。

8.2 排列与组合第八级知识

① 排列 P(n,k)(讲究顺序)

从 n 个不同元素取 k 个排成一列P(n,k) = n! / (n-k)!,如 3 人排队 P(3,2)=6。

② 组合 C(n,k)(不讲究顺序)

从 n 个元素取 k 个成一组C(n,k) = n! / (k!(n-k)!),如 3 人选 2 人 C(3,2)=3。

Python
from math import comb, perm
print(comb(5, 2))    # 10  组合
print(perm(5, 2))    # 20  排列
易错点:① 排列看顺序(排队、排名),组合不看顺序(选人、选物);② C(n,k)=C(n,n-k);③ Python 有内置 comb/perm。

8.3 杨辉三角第八级知识

① 杨辉三角

Python
n = 6
t = [[0] * (n + 1) for _ in range(n + 1)]
t[0][0] = 1
for i in range(1, n + 1):
    for j in range(i + 1):
        t[i][j] = (t[i-1][j-1] if j > 0 else 0) + (t[i-1][j] if j < i else 0)
for i in range(n + 1):
    print(t[i][:i + 1])

杨辉三角第 n 行第 k 个数 = C(n, k)(组合数),每行两边是 1,中间数是肩上两数之和。

生活小例子:搭人墙

杨辉三角就像人墙:最边上站着 1 个人,中间每个人站在下面两个人肩膀上(肩上两数相加),一层层搭起来——每一行的数正好是组合数!

易错点:① 两边是 1,中间 = 左上 + 右上;② 与组合数一一对应;③ 递推生成比阶乘更省事(还能避免溢出)。

8.4 倍增法第八级知识

① 倍增的思想

倍增:每次跳 2 的幂次(1、2、4、8…)来快速前进或向上跳,把 O(n) 优化到 O(log n)。典型应用:快速幂、倍增求 LCA、ST 表

Python
# 快速幂:求 a^b % m
def qpow(a, b, m):
    res = 1
    while b:
        if b & 1: res = res * a % m
        a = a * a % m
        b >>= 1
    return res
print(qpow(2, 10, 1000000007))    # 1024
生活小例子:跳格子省时间

普通一格一格跳 1000 步太慢。倍增=先大步跳 512、256、128…,用二进制把步数拼出来:1000=512+256+128+64+32+8,只跳几次就到位

易错点:① 倍增基于二进制拆分;② 快速幂每次把底数平方、指数除 2;③ 复杂度 O(log n)。

8.5 代数与平面几何(初中数学)第八级知识

① 一元一次 / 二元一次方程

Python
# 解一元一次方程 ax + b = 0
a, b = 2, -8
print(-b / a)        # 4.0
# 解二元一次方程组(用克莱姆法则)
# a1*x + b1*y = c1 ; a2*x + b2*y = c2
a1, b1, c1 = 1, 1, 5
a2, b2, c2 = 2, -1, 1
det = a1 * b2 - a2 * b1
x = (c1 * b2 - c2 * b1) / det   # 2
y = (a1 * c2 - a2 * c1) / det   # 3

② 平面图形面积

图形公式
×
易错点:① 解方程组先算行列式 det,det≠0 才有唯一解;② 面积公式要记牢:三角÷2、圆πr²;③ π 用 math.pi。

8.6 图论算法综合:最小生成树与最短路第八级知识

① 最小生成树(Kruskal / Prim)

Python
# Kruskal:按边权从小到大加边,不成环就选(并查集判环)
edges.sort()                 # [(w, u, v), ...]
fa = list(range(n + 1))
def find(x):
    while fa[x] != x:
        fa[x] = fa[fa[x]]; x = fa[x]
    return x
ans = 0
for w, u, v in edges:
    fu, fv = find(u), find(v)
    if fu != fv:
        fa[fu] = fv; ans += w

② 最短路(Dijkstra / Floyd)

Python
# Dijkstra:单源最短路(边权非负)
import heapq
dist = [float("inf")] * (n + 1); dist[s] = 0
pq = [(0, s)]
while pq:
    d, u = heapq.heappop(pq)
    if d > dist[u]: continue
    for v, w in graph[u]:
        if dist[u] + w < dist[v]:
            dist[v] = dist[u] + w
            heapq.heappush(pq, (dist[v], v))
易错点:① Kruskal 每次选最小边,并查集判环,适合稀疏图;② Dijkstra 用优先队列,边权不能为负;③ Floyd O(n³) 适合小图求全源最短路。

8.7 算法时空效率分析与优化第八级知识

① 时空效率分析

  • 时间:大 O 表示运算量增长趋势;空间:额外开的内存大小;
  • 常见:排序 O(n²)/O(n log n)、查找 O(n)/O(log n)、遍历树图 O(n)、DP 看状态数。

② 算法优化技巧

  • 数学优化:循环求和 → 等差数列公式(1+2+…+n = n(n+1)/2);
  • 数据结构优化:哈希 O(1) 查找、前缀和 O(1) 区间和;
  • 剪枝:搜索时提前排除不可能的分支;
  • 空间换时间:预处理缓存常用结果。
生活小例子:数台阶两种算法

数 1 到 100 的和:循环加要走 100 步,数学公式 100×101÷2 一步算完——数学优化就是这样用公式省掉大量循环!

易错点:① 先分析再优化:先判复杂度能否过题;② 等差数列/等比数列求和公式是经典优化;③ 空间换时间要控制内存。

八级模拟题第八级知识

选择题从 A 市到 B 市有 3 条路,从 B 到 C 有 2 条路,从 A 经 B 到 C 有几种走法?
A. 5B. 6C. 3D. 2
答案:B
分步乘法原理:3×2=6。
选择题C(5, 2) 的值是?
A. 10B. 20C. 5D. 15
答案:A
C(5,2)=5×4/2=10(组合,不看顺序)。
选择题快速幂求 a^b 的时间复杂度是?
A. O(b)B. O(log b)C. O(1)D. O(b²)
答案:B
每次指数减半 → O(log b)。
编程题用 Kruskal 算法求最小生成树的总边权。
答案:参考思路见解析
edges.sort()
fa=list(range(n+1))
def find(x):
    while fa[x]!=x: fa[x]=fa[fa[x]]; x=fa[x]
    return x
ans=0
for w,u,v in edges:
    if find(u)!=find(v):
        fa[find(u)]=find(v); ans+=w
print(ans)
按权排序,并查集判环,不成环就加入。
编程题用 Dijkstra 求单源最短路径。
答案:参考思路见解析
import heapq
dist=[inf]*(n+1); dist[s]=0; pq=[(0,s)]
while pq:
    d,u=heapq.heappop(pq)
    if d>dist[u]: continue
    for v,w in g[u]:
        if dist[u]+w<dist[v]:
            dist[v]=dist[u]+w; heapq.heappush(pq,(dist[v],v))
优先队列每次取当前最小距离的点松弛。