树 Tree
树是有向无环图(directed acyclic graph),有n个节点和n-1个边。
遍历 Traversal
深度优先搜索(DFS,depth-first search)
这里的order是对node来说的,如果node是最先访问的,就是pre-order,如果是中间访问的,就是in-order,如果是最后访问的,就是post-order。
- 前序(pre-order):节点 → 左子树 → 右子树,NLR
- 中序(in-order):左子树 → 节点 → 右子树,LNR
- 后序(post-order):左子树 → 右子树 → 节点,LRN
只要会写前序的递归,另外两种的递归写法差不多。
前序递归(纯函数,dfs()的所有依赖都是以参数形式传进来的)。
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
# 递归
return dfs(root, [])
def dfs(root, resultList):
return resultList + [root.val] + dfs(root.left, []) + dfs(root.right, []) if root else resultList
前序递归(直接处理scope内的变量ans)。
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
# 递归
ans = []
def dfs(root):
if root:
ans.append(root.val)
dfs(root.left)
dfs(root.right)
dfs(root)
return ans
前序迭代(iterative),利用一个栈(stack,FIFO),一直向左到底。
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
# 迭代
ans, stack, node = [], [], root
while stack or node:
while node:
ans.append(node.val)
stack.append(node)
node = node.left
node = stack.pop()
node = node.right
return ans
前序迭代的另一种写法,更常规,更好理解,更推荐!
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
# 迭代
ans, stack = [], [root]
while stack:
node = stack.pop()
if node:
ans.append(node.val)
stack.append(node.right)
stack.append(node.left)
return ans
中序递归,和前序几乎完全一样。
# 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 inorderTraversal(self, root: TreeNode) -> List[int]:
# 递归,和前序差不多
ans = []
def inOrder(node):
if node:
inOrder(node.left)
ans.append(node.val)
inOrder(node.right)
inOrder(root)
return ans
广度优先搜索(BFS,breadth-first search)
广度优先搜索没有什么前中后序。
节点 → 所有子节点 → 子节点的子节点 → ……
LeetCode
| # | 题名 | 难度 | 标签 | 备注 |
|---|---|---|---|---|
| 144 | Binary Tree Preorder Traversal | 中等 | DFS | 简单基础题,不过要熟练掌握递归和迭代两种办法。 |