代码随想录算法训练营第十五天 | 二叉树层序遍历、二叉树的递归遍历、226. 翻转二叉树、101. 对称二叉树

43 阅读4分钟

二叉树层序遍历登场!

102. 二叉树的层序遍历

迭代法

# Time complexity: O(N)
# Space complexity: O(N)
from collections import deque
class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        if root == None:
            return []
​
        queue = deque()
        queue.append(root)
        res = []
        while queue:
            length = len(queue)
            level = []
            for _ in range(length):
                cur = queue.popleft()
                level.append(cur.val)
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
            res.append(level)
​
        return res

递归法

# Time complexity: O(N)
# Space complexity: O(N)
class Solution:
    def levelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        levels = []
        if not root:
            return levels
        
        def helper(node, level):
            # start the current level
            if len(levels) == level:
                levels.append([])
​
            # append the current node value
            levels[level].append(node.val)
​
            # process child nodes for the next level
            if node.left:
                helper(node.left, level + 1)
            if node.right:
                helper(node.right, level + 1)
            
        helper(root, 0)
        return levels

107. 二叉树的层序遍历 II

  • 反转102的答案即可
class Solution:
    def levelOrderBottom(self, root: Optional[TreeNode]) -> List[List[int]]:
        if root == None:
            return []
​
        res = []
        q = deque([root])
        while q:
            l = len(q)
            level = []
            for _ in range(l):
                cur = q.popleft()
                level.append(cur.val)
                if cur.left:
                    q.append(cur.left)
                if cur.right:
                    q.append(cur.right)
            res.append(level)
​
        return res[::-1]

199. 二叉树的右视图

  • 队列中存储每层的所有nodes,res中只记录每层的最后一个node
class Solution:
    def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
        if root == None:
            return []
​
        res = []
        q = deque([root])
        while q:
            l = len(q)
            cur = q[-1]
            res.append(cur.val)
            for _ in range(l):
                cur = q.popleft()
                if cur.left:
                    q.append(cur.left)
                if cur.right:
                    q.append(cur.right)
​
        return res

637. 二叉树的层平均值

  • BFS + 求平均值
class Solution:
    def averageOfLevels(self, root: Optional[TreeNode]) -> List[float]:
        if root == None:
            return []
​
        q = deque([root])
        res = []
​
        while q:
            l = len(q)
            s = 0
            for _ in range(l):
                cur = q.popleft()
                s += cur.val
                if cur.left:
                    q.append(cur.left)
                if cur.right:
                    q.append(cur.right)
            res.append(s/l)
​
        return res

429. N 叉树的层序遍历

  • 用遍历children来代替left,right
class Solution:
    def levelOrder(self, root: 'Node') -> List[List[int]]:
        if root == None:
            return []
​
        q = deque([root])
        res = []
​
        while q:
            l = len(q)
            level = []
            for _ in range(l):
                cur = q.popleft()
                level.append(cur.val)
                for child in cur.children:
                    q.append(child)
​
            res.append(level)
​
        return res

515. 在每个树行中找最大值

  • BFS + 在res中每个level只记录最大值
class Solution:
    def largestValues(self, root: Optional[TreeNode]) -> List[int]:
        if root == None:
            return []
​
        q = deque([root])
        res = []
​
        while q:
            l = len(q)
            max_val = float('-inf')
            for _ in range(l):
                cur = q.popleft()
                max_val = cur.val if cur.val > max_val else max_val
                if cur.left:
                    q.append(cur.left)
                if cur.right:
                    q.append(cur.right)
            res.append(max_val)
​
        return res

116. 填充每个节点的下一个右侧节点指针

  • BFS
  • 每次弹出一个node,将next指向新的队列头
class Solution:
    def connect(self, root: 'Node') -> 'Node':
        if not root:
            return None
​
        queue = deque([root])
        while queue:
            n = len(queue)
            for i in range(n):
                node = queue.popleft()
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
                if i == n - 1:
                    break
                node.next = queue[0]
​
        return root

117. 填充每个节点的下一个右侧节点指针 II

  • 使用层次遍历,解法与116一致
class Solution:
    def connect(self, root: 'Node') -> 'Node':
        if not root:
            return None
​
        queue = deque([root])
        while queue:
            n = len(queue)
            for i in range(n):
                node = queue.popleft()
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
                if i == n - 1:
                    break
                node.next = queue[0]
​
        return root

104. 二叉树的最大深度

  • 层次遍历,每遍历完一层,depth++
class Solution:
    def maxDepth(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0
​
        q = deque([root])
        depth = 0
​
        while q:
            l = len(q)
            for _ in range(l):
                cur = q.popleft()
                if cur.left:
                    q.append(cur.left)
                if cur.right:
                    q.append(cur.right)
            depth += 1
​
        return depth

111. 二叉树的最小深度

  • 层次遍历,若找到叶子节点,直接返回当前depth
class Solution:
    def minDepth(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0
​
        q = deque([root])
        depth = 0
​
        while q:
            l = len(q)
            depth += 1
            for _ in range(l):
                cur = q.popleft()
                if not cur.left and not cur.right:
                    return depth
                if cur.left:
                    q.append(cur.left)
                if cur.right:
                    q.append(cur.right)
​
        return depth

226. 翻转二叉树

递归法:前序遍历

  • 翻转就是递归交换左右子树
class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        if not root:
            return None
        root.left, root.right = root.right, root.left  # 中
        self.invertTree(root.left)  # 左
        self.invertTree(root.right)  # 右
        return root

迭代法:前序遍历

  • 注意进栈顺序和弹出顺序相反
class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        if not root:
            return None
​
        stack = deque([root])
        while stack:
            cur = stack.pop()
            # root
            cur.left, cur.right = cur.right, cur.left
            # right
            if cur.right:
                stack.append(cur.right)
            # left
            if cur.left:
                stack.append(cur.left)
​
        return root

迭代法:层序遍历

class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        if not root:
            return None
​
        q = deque([root])
        while q:
            cur = q.popleft()
            cur.left, cur.right = cur.right, cur.left
            # left
            if cur.left:
                q.append(cur.left)
            # right
            if cur.right:
                q.append(cur.right)
​
        return root

101. 对称二叉树

递归法

  • 递归比较左右子树的外侧节点和内侧节点
class Solution:
    def isSymmetric(self, root: Optional[TreeNode]) -> bool:
        if not root:
            return True
        return self.helper(root.left, root.right)
​
    def helper(self, left, right):
        if left == None and right != None:
            return False
        elif left != None and right == None:
            return False
        # leaf node
        elif left == None and right == None:
            return True
​
        if left.val != right.val:
            return False
​
        outside = self.helper(left.left, right.right)
        inside = self.helper(left.right, right.left)
        is_same = outside and inside
        
        return is_same

迭代法:使用队列

  • 进队列顺序与出队列顺序一致
class Solution:
    def isSymmetric(self, root: Optional[TreeNode]) -> bool:
        if not root:
            return True
        
        queue = deque()
        queue.append(root.left) #将左子树头结点加入队列
        queue.append(root.right) #将右子树头结点加入队列
        
        while queue: #接下来就要判断这这两个树是否相互翻转
            leftNode = queue.popleft()
            rightNode = queue.popleft()
            if not leftNode and not rightNode: #左节点为空、右节点为空,此时说明是对称的
                continue
            
            #左右一个节点不为空,或者都不为空但数值不相同,返回false
            if not leftNode or not rightNode or leftNode.val != rightNode.val:
                return False
            
            # outside
            queue.append(leftNode.left) #加入左节点左孩子
            queue.append(rightNode.right) #加入右节点右孩子
            # inside
            queue.append(leftNode.right) #加入左节点右孩子
            queue.append(rightNode.left) #加入右节点左孩子
            
        return True