代码随想录算法训练营 Day15|层序遍历10, 226.翻转二叉树, 101.对称二叉树 2

Day15|层序遍历10, 226.翻转二叉树, 101.对称二叉树 2

层序遍历 10

层序遍历
层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。
层序遍历方式就是图论中的广度优先遍历。
需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑

102.二叉树的层序遍历

思路

根据代码随想录视频总结层序遍历要点

  1. 使用队列实现层序遍历。初始时,先将参数根节点root加入队列
  2. while循环,终止条件:队列中没有元素
  3. 注意要先记录当前层的节点个数size,用于控制队列中弹出的节点数量
  4. 第一层循环内创建一个数组,用于存放当前层的节点
  5. 第二层的while循环,利用size,也就是当前队列的长度作为循环的终止条件
  6. 第二层while循环内,实现 1)弹出该层节点、2)将该节点的字节点加入队列
  7. 最后将每一层的数组放入一个二维数组中

尝试根据思路写代码:

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需要注意的点:

  1. 一开始需要判断root是否为空,如果为空,直接返回空列表
  2. deque判断是否为空,可以直接while queue:
  3. python中的for循环范围不会中途改变,因此可以在for循环的条件范围直接使用len(queue)
  4. 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
  • 18
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值