文章链接:代码随想录
视频链接:关于二叉树,你该了解这些!| 二叉树理论基础一网打尽,二叉树的种类、二叉树的存储方式、二叉树节点定义、二叉树的遍历顺序_哔哩哔哩_bilibili
又是隔了好几天才补上二叉树的part 1。。。老师的讲解很系统化,从理论基础到递归遍历、迭代遍历、层序遍历,一环接一环,让人很容易跟上节奏,思路清晰,逐步巩固。
递归遍历 Leetcode 144\145\94
重点三要素(摘自代码随想录):
确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。
确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。
确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。
# (递归法)前序遍历: 中左右
# 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 preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
res = []
def dfs(node):
if node is None:
return
# 以下三行代码调整顺序即可变为中序、后序遍历
res.append(node.val)
dfs(node.left)
dfs(node.right)
dfs(root)
return res
迭代遍历 Leetcode 144\145\94
用栈来实现,重点要注意访问node和处理node的顺序,尤其是中序遍历。
(统一迭代法暂时跳过。)
前序、后序遍历:
前序遍历是中左右,每次先处理的是中间节点,那么先将根节点放入栈中,然后将右孩子加入栈,再加入左孩子(先放右孩子才能实现出栈时的中左右顺序),要访问的元素和要处理的元素顺序是一致的,都是中间节点
后序遍历是左右中,那么只需要调整一下前序遍历的代码顺序:
(前序)中左右--->>> (调整代码左右顺序)中右左--->>> (反转result数组)左右中
# (迭代)前序遍历
# 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 preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
stack = [root]
result = []
while stack:
node = stack.pop()
result.append(node.val)
# 前序遍历顺序:中-左-右,入栈顺序:中-右-左
# 互换以下代码调整为后序遍历:原顺序 左-右-中
# 入栈顺序:中-左-右 出栈顺序:中-右-左, 最后翻转结果
if node.right:
stack.append(node.right)
if node.left:
stack.append(node.left)
return result
中序遍历:左中右
先访问的是二叉树顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点(也就是在把节点的数值放进result数组中),处理顺序和访问顺序是不一致的。
# (迭代法)中序遍历:左中右
# 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: Optional[TreeNode]) -> List[int]:
if not root:
return []
stack = []
cur = root
res = []
while cur or stack:
# 先迭代访问最底层的左子树结点
if cur:
stack.append(cur)
cur = cur.left
# 到达最左结点后处理栈顶结点
else:
cur = stack.pop()
res.append(cur.val)
# 取栈顶元素右结点
cur = cur.right
return res
层序遍历 leetcode 102
注意:进行每一层的遍历时,一定要使用固定大小size,不能用len(queue), 因为queue大小是不断变化的
在这道题里面直接用len(queue)进行遍历也能AC,但在其他题中就会因为这个问题引起错误,如leetcode199
# 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]]:
if not root:
return []
queue = collections.deque([root])
result = []
while queue:
size = len(queue)
data = []
for _ in range(size):
cur = queue.popleft()
data.append(cur.val)
if cur.left:
queue.append(cur.left)
if cur.right:
queue.append(cur.right)
result.append(data)
return result