⑥ leetcode刷题汇总(二叉树)
一、二叉树的基础知识

1. 二叉树节点类(TreeNode)的定义
二叉树的最小单元是 “节点”,每个节点包含三个核心部分:
val:节点存储的值(可以是整数、字符串等);left:指向左子节点的指针(初始为None,表示没有左子节点);right:指向右子节点的指针(初始为None,表示没有右子节点)。
class TreeNode:def __init__(self, val=0, left=None, right=None):self.val = val # 节点的值self.left = left # 左子节点(默认None)self.right = right # 右子节点(默认None)
| 知识类别 | 核心内容 | 对应 LeetCode 典型题目 |
|---|---|---|
| 基本结构 | 1. 节点:val + left(左指针)+ right(右指针) 2. 特性:每个节点最多 2 子节点,递归定义 | 所有二叉树题基础(144. 前序遍历、 94. 中序遍历) |
| 核心遍历方式 | 1. DFS(深度优先搜索) - 前序:根→左→右(递归 / 栈) - 中序:左→根→右(递归 / 栈,BST 升序) - 后序:左→右→根(递归 / 栈) 2. BFS(广度优先搜索): 层序遍历(队列,按层存) | 144. 前序遍历、 94. 中序遍历、 145. 后序遍历、 102. 层序遍历 |
| 常见性质 | 1. 第 k 层最多 2^(k-1) 个节点(根为第 1 层) 2. 深度 h:最少 h 个节点(链状),最多 2^h-1 个(满树) 3. 完全二叉树:节点 i 的左 = 2i、右 = 2i+1 | 104. 二叉树的最大深度、 222. 完全二叉树的节点个数 |
| 核心操作 | 1. 求深度:递归(左右子树最大深度 + 1) 2. 求直径:左右子树深度和的最大值 3. 构建树:用遍历序列(如前 + 中)+ 哈希表定位根 | 104. 最大深度、 543. 二叉树的直径、 105. 从前序与中序构造二叉树 |
| 特殊类型树 | 1. BST:左 < 根 < 右,中序升序 2. 平衡树:左右子树高度差≤1 3. 完全树:除最后一层外满,最后一层左对齐 | 98. 验证二叉搜索树、 110. 平衡二叉树、 222. 完全二叉树节点数 |
二、102. 二叉树的层序遍历
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:# result: 最终的二维数组# queue:存持续存储待处理节点,可包括当前层→下一层的节点 ,重点过程可能有当前层 + 下一层(node.left, node.right)# node: 具体的节点、# layer_size:记录当前层的节点个数# current_layer:存储当前层节点 所有的值,存 “值”(node.val)→ 为了生成最终的结果列表;#1. 处理特殊情况if not root: return []#2.初始化:结果列表 + 队列(固定结构)result = [] # 最终的二位数组队列queue = [root]#3.循环处理每一层while queue: layer_size = len(queue) # 记录当前层的节点个数current_layer = [] # 存储当前层节点 所有的值# 将根节点赋值for _ in range(layer_size):node = queue.pop(0) # 取出头节点,pop括号里还能有值? 我记得处理堆栈里就不能有值current_layer.append(node.val)# 头节点的值加到 current_layer# 增加头节点的左叶子节点和右叶子节点(如果有)if node.left:queue.append(node.left)if node.right:queue.append(node.right)# 当前层加入到最终结果里result.append(current_layer)return result
1.对每个变量的理解
- 首先,得有个地方装最终结果(
result);- 其次,得有个地方存 “还没处理的下一层节点”(
queue);- 然后,处理当前层时,必须知道 “这一层有多少个节点”,否则会把下一层的节点混进来(
layer_size);- 最后,处理当前层时,得临时存一下这一层的节点值(
current_layer),收集完再放进最终结果。
2. 二叉树为什么要用二维数组表示
二维数组直观展示层级结构,方便人理解
例如:
1/ \2 3/ \
4 5用二维数组表示为 [[1], [2,3], [4,5]],一眼就能看出:
第 0 层(或第 1 层)有节点 1;
第 1 层(或第 2 层)有节点 2,3;
第 2 层(或第 3 层)有节点 4,5。
3. pop的用法(python)
| 对比维度 | pop() | pop(0) |
|---|---|---|
| 是否需要参数 | 不需要(默认无参) | 需要传参数 0 |
| 删除 / 返回位置 | 删除列表最后一个元素,返回该元素 | 删除列表第一个元素,返回该元素 |
| 对应数据结构 | 栈(LIFO:后进先出) | 队列(FIFO:先进先出) |
| 时间复杂度 | O (1)(直接操作末尾,无需移动元素) | O (n)(删除第一个元素后,需移动后面所有元素) |
| 典型使用场景 | 栈操作(如深度优先遍历的回溯) | 队列操作(如层序遍历的节点处理) |
1. 执行 pop()(无参),对应场景:比如 “栈” 的 “出栈” 操作 —— 最后加入的元素先被取出(比如递归回溯时记录路径)。nums = [1, 2, 3, 4]
deleted_val = nums.pop() # 无参,删除最后一个元素
print("删除的值:", deleted_val) # 输出:删除的值:4
print("操作后列表:", nums) # 输出:操作后列表:[1, 2, 3]2. 执行 pop(0)(传参 0)
nums = [1, 2, 3, 4]
deleted_val = nums.pop(0) # 传参 0,删除第一个元素
print("删除的值:", deleted_val) # 输出:删除的值:1
print("操作后列表:", nums) # 输出:操作后列表:[2, 3, 4]对应场景:比如 “队列” 的 “出队” 操作 —— 最先加入的元素先被取出(就像你之前层序遍历里,用 pop(0) 取出队列头部的节点)。
