Day15|层序遍历10, 226.翻转二叉树, 101.对称二叉树 2
层序遍历 10
层序遍历
层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。
层序遍历方式就是图论中的广度优先遍历。
需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。
102.二叉树的层序遍历
思路
根据代码随想录视频总结层序遍历要点:
- 使用队列实现层序遍历。初始时,先将参数根节点root加入队列
- while循环,终止条件:队列中没有元素
- 注意要先记录当前层的节点个数size,用于控制队列中弹出的节点数量
- 第一层循环内创建一个数组,用于存放当前层的节点
- 第二层的while循环,利用size,也就是当前队列的长度作为循环的终止条件
- 第二层while循环内,实现 1)弹出该层节点、2)将该节点的字节点加入队列
- 最后将每一层的数组放入一个二维数组中
尝试根据思路写代码:
class Solution:
def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
queue = deque([])
result = []
if root.val:
queue.append(root)
while len(queue):
size = queue.size()
tmp = []
while size:
node = queue.popleft()
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
size -= 1
result.append(tmp)
return result
问题:
deque如何判断是否为空
deque如何判断size, 没有queue.size这种用法,程序出错
Python需要注意的点:
- 一开始需要判断root是否为空,如果为空,直接返回空列表
- deque判断是否为空,可以直接
while queue:
- python中的for循环范围不会中途改变,因此可以在for循环的条件范围直接使用
len(queue)
- deque可以使用
len(queue)
判断size大小
最终代码:
class Solution:
def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
if not root:
return []
queue = deque([root])
result = []
while queue:
tmp = []
for _ in range(len(queue)):
node = queue.popleft()
tmp.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
result.append(tmp)
return result
107. 二叉树的层序遍历 II
思路
可以先实现由上至下的层序遍历,再翻转一下。
不确定如何实现二维数组反转的代码。
直接实现:因为一开始只给了根节点,不知道如何先找到底层最左边的叶子节点,以及该叶子节点的父节点。
或者可以每一层的列表放入二维数组中时,反着加入。
Python实现要点:
切片法可以反转二维数组
# 翻转行:
arr[::-1]
# 翻转列:
arr[:,::-1]
最终代码:
class Solution:
def levelOrderBottom(self, root: Optional[TreeNode]) -> List[List[int]]:
if not root:
return []
queue = deque([root])
result = []
while queue:
tmp = []
for _ in range(len(queue)):
node = queue.popleft()
tmp.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
result.append(tmp)
return result[::-1]
199. 二叉树的右视图
思路
按照层序遍历的模式,只不过每次只记录当前层的最后一个元素。
或者取层序遍历结果的最后一个值。
按照第二个思路写代码:
class Solution:
def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
queue = deque([root])
result = []
last = []
while queue:
tmp = []
for _ in range(len(queue)):
node = queue.popleft()
tmp.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
result.append(tmp)
for i in result:
last.append(i[-1])
return last
成功通过!
代码随想录 思路:
层序遍历的时候,判断是否遍历到单层的最后面的元素,如果是,就放进result数组中,随后返回result
最终代码:
class Solution:
def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
queue = deque([root])
result = []
while queue:
level_size = len(queue)
for i in range(level_size):
node = queue.popleft()
if i == level_size - 1:
result.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return result
由于此时需要判断节点是否为该层最后一个节点,所以需要额外记录每一层的size
637. 二叉树的层平均值
只需要将每层的平均值加入最终的数组中
class Solution:
def averageOfLevels(self, root: Optional[TreeNode]) -> List[float]:
if not root:
return []
result = []
queue = deque([root])
while queue:
level = 0
level_size = len(queue)
for _ in range(level_size):
node = queue.popleft()
level += node.val
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
result.append(level/level_size)
return result
429. N 叉树的层序遍历
思路
不确定如何判断当前节点下有几个子节点。
使用while判断node.children 是否有值,如果有,就将其加入队列。
但是不知道children的下一个怎么用代码表示
尝试写代码:
class Solution:
def levelOrder(self, root: 'Node') -> List[List[int]]:
if not root:
return []
queue = deque([root])
result = []
while queue:
level = []
for _ in range(len(queue)):
node = queue.popleft()
level.append(node.val)
# children = 0
while node.children:
queue.append(node.children)
# node.children = node.children
result.append(level)
return result
结果是超出时间限制,因为没有对node.children做处理
注意:
N叉树中,node.children
是一个集合(列表),可以用for循环逐个加入队列,也可以用extend
全部加入。
最终代码
class Solution:
def levelOrder(self, root: 'Node') -> List[List[int]]:
if not root:
return []
queue = deque([root])
result = []
while queue:
level = []
for _ in range(len(queue)):
node = queue.popleft()
level.append(node.val)
for child in node.children:
queue.append(child)
# queue.extend(node.children)
result.append(level)
return result
515. 在每个树行中找最大值
思路
在层序遍历基础上,只返回该层最大值
class Solution:
def largestValues(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
queue = deque([root])
result = []
while queue:
level = []
for _ in range(len(queue)):
node = queue.popleft()
level.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
result.append(max(level))
return result
根据代码随想录文章,只需要每一层只记录最大的节点值
class Solution:
def largestValues(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
queue = deque([root])
result = []
while queue:
max_level = float('-inf')
for _ in range(len(queue)):
node = queue.popleft()
max_level = max(max_level, node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
result.append(max_level)
return result
116. 填充每个节点的下一个右侧节点指针
思路
利用每一层的size,当节点为该层最后一个节点时,node.next = None
;其余时候,node.next = queue[0]
,即当前队列中的首个元素。
class Solution:
def connect(self, root: 'Optional[Node]') -> 'Optional[Node]':
if not root:
return root
queue = deque([root])
while queue:
level_size = len(queue)
for i in range(level_size):
node = queue.popleft()
if i == level_size - 1:
node.next = None
else:
node_r = queue[0]
node.next = node_r
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return root
成功通过!
代码随想录的思路:
在单层遍历的时候记录一下本层的头部节点,然后在遍历的时候让前一个节点指向本节点
在每层开头初始化一个节点prev,作为当前节点的前一节点,方便更改除了最后一个节点之外的其他节点的next指针
最终代码
class Solution:
def connect(self, root: 'Optional[Node]') -> 'Optional[Node]':
if not root:
return root
queue = deque([root])
while queue:
level_size = len(queue)
prev = None
for i in range(level_size):
node = queue.popleft()
if prev:
prev.next = node
prev = node
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return root