树的遍历

01 / 一句话本质

任何树的遍历算法都会恰好访问每个节点一次 —— 唯一变化的,是"访问"发生在对子节点递归下降的哪一刻。
题目按指定顺序遍历一棵二叉树二叉树[1, 2, 3, 4, 5, ·, 6]遍历前序
123456
输出—— 暂无 ——
深度优先 —— 前序在向子节点递归之前访问节点。
0 / 7
正在访问
已访问
0 / 6
遍历
前序
0 / 7

02 / 模式骨架

# 深度优先 —— 三种变体只是"访问"放在不同位置traverse(node):if node is null: returnvisit(node) // 前序traverse(node.left)visit(node) // 中序traverse(node.right)visit(node) // 后序# 广度优先 —— 迭代,基于队列level_order(root):q [root]while q not empty:node q.dequeue(); visit(node)enqueue node.left, node.right

03 / 什么时候用这个模式

"BST 的中序"
二叉搜索树的有序输出来自中序 —— 这是 BST 的性质, 并不是中序遍历本身的一般性质。
"逐层"
需要按行处理整棵树 —— 节点深度、锯齿形输出、"找树的右视图"等等。 基于队列的层序正是这件工具。
"自底向上 / 先子后父"
只有先知道子节点的答案,才能算出当前节点的答案 —— 子树和、高度、路径等。后序能保证子节点先被访问。
"序列化 / 克隆"
把一棵树写成字符串,或是逐节点复制。常用前序外加显式的 null 标记 —— 这样能无歧义地刻画结构。

04 / 常见坑

该用后序时用了中序。
任何需要根据子节点答案推父节点答案的事情 —— 子树和、高度、直径 —— 都必须在父节点之前访问子节点。这就是后序。 中序会让部分子节点访问得太晚。
漏掉判空。
递归遍历的第一行就是 if node is null: return。 漏掉它,就会在每个叶子缺失的子节点处解引用 null。 动画把这点显式呈现 —— 空子树根本不渲染。
把调用栈当成输出顺序。
递归天然的调用栈并不是访问的顺序。一个节点会在自己前序访问之前就压入栈, 直到后序访问之后才弹出 —— 这是同一节点的三个不同"时刻"。

05 / 去 LeetCode 上练习

中等42

01Validate Binary Search Tree— LC 9802Recover Binary Search Tree— LC 9903Binary Tree Level Order Traversal— LC 10204Binary Tree Zigzag Level Order Traversal— LC 10305Construct Binary Tree from Preorder and Inorder Traversal— LC 10506Construct Binary Tree from Inorder and Postorder Traversal— LC 10607Binary Tree Level Order Traversal II— LC 10708Path Sum II— LC 11309Sum Root to Leaf Numbers— LC 12910Binary Search Tree Iterator— LC 17311Binary Tree Right Side View— LC 19912Kth Smallest Element in a BST— LC 23013Lowest Common Ancestor of a Binary Search Tree— LC 23514Lowest Common Ancestor of a Binary Tree— LC 23615Binary Tree Vertical Order Traversal— LC 31416House Robber III— LC 33717N-ary Tree Level Order Traversal— LC 42918Path Sum III— LC 43719Serialize and Deserialize BST— LC 44920Delete Node in a BST— LC 45021Convert BST to Greater Tree— LC 53822Maximum Width of Binary Tree— LC 66223Insert into a Binary Search Tree— LC 70124Smallest Subtree with all the Deepest Nodes— LC 86525Construct Binary Tree from Preorder and Postorder Traversal— LC 88926Distribute Coins in Binary Tree— LC 97927Smallest String Starting From Leaf— LC 98828Construct Binary Search Tree from Preorder Traversal— LC 100829Binary Search Tree to Greater Sum Tree— LC 103830Lowest Common Ancestor of Deepest Leaves— LC 112331Tree Diameter— LC 124532Smallest Common Region— LC 125733Deepest Leaves Sum— LC 130234Maximum Product of Splitted Binary Tree— LC 133935Longest ZigZag Path in a Binary Tree— LC 137236Balance a Binary Search Tree— LC 138237Count Good Nodes in Binary Tree— LC 144838Diameter of N-Ary Tree— LC 152239Lowest Common Ancestor of a Binary Tree II— LC 164440Lowest Common Ancestor of a Binary Tree III— LC 165041Create Binary Tree From Descriptions— LC 219642Most Profitable Path in a Tree— LC 2467