LeetCode:二叉树(二)

本组囊括二叉树各序遍历的题目,难度不等。

 

144. Binary Tree Preorder Traversal

题目描述:中等

解法一:递归

递归的dfs很简单,特别是用于前中后序三种遍历,只要该节点做好自己的事,就开启下一个顺序的节点的递归。

 1 class Solution:
 2     def preorderTraversal(self, root: TreeNode) -> List[int]:
 3         if not root:
 4             return []
 5         def dfs(root):
 6             if root != None:
 7                 res.append(root.val)
 8                 dfs(root.left)
 9                 dfs(root.right)
10         res = []
11         dfs(root)
12         return res

 

解法二:迭代

这里使用一种能够统一三种序遍历的迭代模板来写。(递归转迭代)

思路:递归的本质就是压栈,了解递归本质后就完全可以按照递归的思路来迭代。

怎么压,压什么?压的当然是待执行的内容,后面的语句先进栈,所以进栈顺序就决定了前中后序。

我们需要一个标志区分每个递归调用栈,这里使用None来表示。每个非空节点增加None节点,方便判断是否结束了一个递归调用栈,结束了才能返回该节点的值.。细节见注释

 1 class Solution:
 2     def preorderTraversal(self, root: TreeNode) -> List[int]:        
 3         if not root:
 4             return []
 5         res = []
 6         stack = [root]
 7         while stack:
 8             node = stack.pop(-1)
 9             if node == None:
10                 node = stack.pop(-1)
11                 res.append(node.val)
12             else: ## else后的顺序决定前中后序
13                 if node.right:
14                     stack.append(node.right)
15                 if node.left:
16                     stack.append(node.left)
17                 stack.append(node)
18                 stack.append(None)
19         return res

 

 

94. Binary Tree Inorder Traversal

题目描述:中等

解法一:递归

递归的dfs很简单,特别是用于前中后序三种遍历,只要该节点做好自己的事,就开启下一个顺序的节点的递归。

 1 class Solution:
 2     def preorderTraversal(self, root: TreeNode) -> List[int]:
 3         self.res = []
 4         def dfs(root):
 5             if root != None:
 6                 dfs(root.left)
 7                 self.res.append(root.val)
 8                 dfs(root.right)
 9         dfs(root)
10         return self.res

 

 

解法二:迭代

这里使用一种能够统一三种序遍历的迭代模板来写。(递归转迭代)

思路:同上,注意else后的顺序决定了是前中还是后序。

 1 class Solution:
 2     def preorderTraversal(self, root: TreeNode) -> List[int]:        
 3         if not root:
 4             return []
 5         stack = [root]
 6         res = []
 7         while stack:
 8             node = stack.pop(-1)
 9             if node is None:
10                 node = stack.pop(-1)
11                 res.append(node.val)
12             else:
13                 if node.right:
14                     stack.append(node.right)
15                 stack.append(node)
16                 stack.append(None)
17                 if node.left:
18                     stack.append(node.left)
19         return res
20         # 时间复杂度:O(N)
21         # 空间复杂度:O(N)

 

 

145. Binary Tree Postorder Traversal

题目描述:困难

 

解法一:递归

递归的dfs很简单,特别是用于前中后序三种遍历,只要该节点做好自己的事,就开启下一个顺序的节点的递归。

 1 class Solution:
 2     def preorderTraversal(self, root: TreeNode) -> List[int]:
 3         if not root:
 4             return []
 5         res = []
 6         def dfs(root):
 7             if root != None:
 8                 dfs(root.left) # 框架递归左子树
 9                 dfs(root.right) # 框架递归右子树
10                 res.append(root.val) # 本节点输出根节点值
11         dfs(root)
12         return res

 

 

解法二:迭代

这里使用一种能够统一三种序遍历的迭代模板来写。(递归转迭代)

思路:同上。

 1 class Solution:
 2     def preorderTraversal(self, root: TreeNode) -> List[int]:        
 3         if not root:
 4             return []
 5         res = []
 6         stack = [root] # 对固定为初始化为root
 7         while stack:
 8             node = stack.pop(-1) # 每次循环都首先取出栈顶当做当前节点,并弹出
 9             if node == None: # 空节点表示之前已经访问过了,现在需要处理除了递归之外的内容
10                 node = stack.pop(-1) # 第二次弹出节点(彻底从栈中移除)
11                 res.append(node.val) # 记录该节点值
12 
13             ######   else之前的代码都是通用模板(前中后) ##### 只用改else后的代码
14             else:# 若遇到的是非空节点
15                 stack.append(node) # 在右节点之前重新插入该节点,以便在最后处理(访问值)
16                 stack.append(None) # None跟随node插入,标识已经访问过,还没有被处理
17                 if node.right: # 先右后左,因为栈后进先出,先出左边的节点。
18                     stack.append(node.right)
19                 if node.left:
20                     stack.append(node.left)
21         return res
22         # 时间复杂度:O(N)
23         # 空间复杂度:O(2N)最多

 

102. Binary Tree Level Order Traversal

题目描述:中等

解法一:BFS

二维数组,每次返回一层,广度优先遍历BFS,很明显地想到队列;
我们想到的层序是每次遍历完一个节点,再添加他的左右节点,这必须要求要先弹出上一层的节点,即先进来的节点所有我们借助队列来实现。

 1 class Solution:
 2     def levelOrder(self, root: TreeNode) -> List[List[int]]:
 3         ans = [] # 存储结果的二维数组
 4         if not root:
 5             return ans
 6         queue = [root]
 7         while dueue:
 8             size = len(queue) # 当前队列长度,即当前层有几个节点,全部加入一维数组中
 9             res = [] # 每遍历完一层,则清空res
10             for i in range(size):
11                 curr = dueue.pop(0) # 先进先出
12                 if curr.left:
13                     dueue.append(curr.left)
14                 if curr.right:
15                     dueue.append(curr.right)
16                 res.append(curr.val) # 该层的所有节点加入队列
17             ans.append(res) # 该层的一维数组加入二维数组
18         return ans
19         # 时间复杂度:每个点进队出队各一次,故渐进时间复杂度为O(n)。
20         # 空间复杂度:队列中元素的个数不超过 n 个,故渐进空间复杂度为O(n)。

 

 

107. Binary Tree Level Order Traversal II

题目描述:简单

解法一:BFS

同上一题很像,也是要求输出二维数组:但这里需要的是反转输出。
取巧的方法,结果数组直接reverse即可。

 1 class Solution:
 2     def levelOrderBottom(self, root: TreeNode) -> List[List[int]]:
 3         ans = [] # 存储结果的二维数组
 4         if not root:
 5             return ans
 6         dueue = [root] # 初始队列
 7         while dueue:
 8             size = len(dueue) # 当前层的节点数
 9             res = [] # 存储每层节点的一维数组,每遍历完一层清空
10             for _ in range(size): # 遍历当前层节点,都记录下来
11                 curr = dueue.pop(0) # 先进先出
12                 res.append(curr.val) # 当前层节点值依次加入数组
13                 if curr.left: # 当前节点的左孩子加入队列
14                     dueue.append(curr.left)
15                 if curr.right: # 当前节点的右孩子加入队列
16                     dueue.append(curr.right)
17             ans.append(res) # 加入一维数组
18         return ans[::-1] # 反转输出

 

 

103. Binary Tree Zigzag Level Order Traversal

题目描述:中等

解法一:BFS

类似层序,使用迭代+BFS方法,借助队列实现;
关键在于如何层与层交替改变顺序,最取巧的方法,奇偶反转数组即可。

 1 class Solution:
 2     def zigzagLevelOrder(self, root: TreeNode) -> List[List[int]]:
 3         if not root:
 4             return []
 5         ans = [] # 存储结果的二维数组
 6         dueue = [root]
 7         i = 0 
 8         while dueue:
 9             size = len(dueue)
10             res = []
11             for _ in range(size):
12                 curr = dueue.pop(0)
13                 res.append(curr.val)
14                 if curr.left:
15                     dueue.append(curr.left)
16                 if curr.right:
17                     dueue.append(curr.right)
18             if i % 2 == 1:# 判断奇偶层,需要反转的时候反转
19                 res = res[::-1]
20             ans.append(res) # 每次加一层
21             i += 1 # 每次自+1
22         return ans
23         # 时间复杂度:每个点进队出队各一次,故渐进时间复杂度为O(n)。
24         # 空间复杂度:队列中元素的个数不超过 n 个,故渐进空间复杂度为O(n)。

 

posted @ 2020-11-10 10:34  Jesse-jia  阅读(123)  评论(0编辑  收藏  举报