leetcode 【二叉树的各种遍历】
1. 前序遍历
题目链接
https://leetcode-cn.com/problems/binary-tree-preorder-traversal/
解题思路与代码思路:
递归法
前序遍历就是“根节点–左子树–右子树”的顺序去遍历整棵树,递归可以完美匹配这个过程。
迭代法
把递归所隐含的栈结构构建出来,模拟递归过程。只要左子树为空就pop出来,然后看右边。
代码:
递归法
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
def preorder(root):
if not root:
return
res.append(root.val)
preorder(root.left)
preorder(root.right)
res = []
preorder(root)
return res
迭代法
- 辅助指针写法
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
res = list()
if not root:
return res
stack = []
node = root
while stack or node:
while node: #移动指针node,重复的找左树直到为空
res.append(node.val) #当前值存入result
stack.append(node) #加入栈中
node = node.left #跳到左子树
node = stack.pop() # 遇到空的情况会一直pop,最后又回到根节点
node = node.right
return res
- 利用了栈的属性
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
res = list()
if not root:
return res
stack = [root]
while stack:
node = stack.pop()
if node:
res.append(node.val)
if node.right: #先放右节点,后放左节点,因为会把最新进栈的pop出来存入res
stack.append(node)
if node.left:
stack.append(node.left)
return res
复 杂 度 分 析 : \color{red}{复杂度分析:} 复杂度分析:
- 递归法
- 时间复杂度:O(N),遍历每个节点
- 空间复杂度:O(N),递归中栈的开销,平均情况下为 O(logn),最坏情况下树呈现链状,为 O(n)
- 迭代法
- 时间复杂度:O(N),遍历每个节点
- 空间复杂度:O(N),递归中栈的开销,平均情况下为 O(logn),最坏情况下树呈现链状,为 O(n)
2. 中序遍历
解题思路与代码思路:
递归法
递归法只需要调整前序遍历的res.append(root.val)的位置即可完成,所以不多写了。
迭代法
迭代法其实就是模拟递归法的入栈出栈过程,因为是左—中---右的顺序,所以就先把节点入栈,不断进入左子树入栈,直到为空,就可以出栈存入到res当中,并且转移到该节点的右树上。
代码:
迭代法
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
res = list()
if not root:
return res
stack = []
node = root
while stack or node:
while node:
stack.append(node)
node = node.left
node = stack.pop()
res.append(node.val)
node = node.right
return res
复 杂 度 分 析 : \color{red}{复杂度分析:} 复杂度分析:
- 时间复杂度:O(N)
- 空间复杂度:O(N)
3. 后序遍历
解题思路与代码思路:
递归法
递归法只需要调整前序遍历的res.append(root.val)的位置即可完成,所以不多写了。
迭代法
迭代法有两种方式:
-
反向输出
后序遍历的输出是《左右根》的方式输出,我们可以按照《根右左》的方式去存入栈,然后反向输出就可以了。 -
flag标识辅助记录
创建一个flag标识,记录是否遍历过一次本节点,这里我们使用了元组去记录,更加方便
代码:
迭代法
class Solution:
def postorderTraversal(self, root: TreeNode) -> List[int]:
if not root: return []
stack,res = [(0,root)],[]
while stack:
flag,node = stack.pop()
if not node: continue
if flag == 1:
res.append(node.val)
else:
stack.append((1,node))
stack.append((0,node.right))
stack.append((0,node.left))
return res
复 杂 度 分 析 : \color{red}{复杂度分析:} 复杂度分析:
- 时间复杂度:O(N)
- 空间复杂度:O(N)
4. 层次遍历
解题思路与代码思路:
队列法
层次遍历使用了广度优先搜索,广度优先搜索主要使用队列实现,collection.dequeue.
代码:
队列法
def levelOrder(self,root):
if not root:return []
res,q = [],[root]
while q:
n = len(q)
level = []
for i in range(n):
node = q.pop(0)
level.append(node.val)
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
res.append(level)
return res
复 杂 度 分 析 : \color{red}{复杂度分析:} 复杂度分析:
- 时间复杂度:O(N)
- 空间复杂度:O(N)