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

层序遍历:102. 二叉树的层序遍历

队列实现,que不为空说明还有层需要处理,处理这一层。先把本层结果进res数组,再把下一层(如果有)进队。

from collections import deque
class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        if not root: return []
        que = deque([root])
        res = []

        while que:
            res.append([item.val for item in que])
            for _ in range(len(que)):
                node = que.popleft()
                if node.left: que.append(node.left)
                if node.right: que.append(node.right)
        return res

递归实现,使用辅助函数,跳过!

class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        result = []
        
        def traverse(node, depth):
            if not node:
                return
            
            # 如果当前深度还没有对应的列表,创建一个
            if len(result) == depth:
                result.append([])
            
            # 将当前节点的值添加到对应深度的列表中
            result[depth].append(node.val)
            
            # 递归处理左子树和右子树,深度加1
            traverse(node.left, depth + 1)
            traverse(node.right, depth + 1)
        
        traverse(root, 0)
        return result

下面简单记录下其他9个层序遍历题目。

107. 二叉树的层序遍历 II

from collections import deque
class Solution:
    def levelOrderBottom(self, root: Optional[TreeNode]) -> List[List[int]]:
        if not root:
            return []
        res = []
        que = deque([root])

        while que:
            res.append([item.val for item in que])
            for _ in range(len(que)):
                node = que.popleft()
                if node.left: que.append(node.left)
                if node.right: que.append(node.right)
        return res[::-1]

199. 二叉树的右视图

from collections import deque
class Solution:
    def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
        if not root:
            return []
        res = []
        que = deque([root])

        while que:
            level_size = len(que)
            for _ in range(level_size):
                node = que.popleft()
                if _ == level_size - 1:
                    res.append(node.val)
                if node.left:
                    que.append(node.left)
                if node.right:
                    que.append(node.right)
        return res

637. 二叉树的层平均值

from collections import deque
class Solution:
    def averageOfLevels(self, root: Optional[TreeNode]) -> List[float]:
        if not root:
            return []
        res = []
        que = deque([root])

        while que:
            level_length = len(que)
            res.append(sum([item.val  for item in que]) / level_length)
            for _ in range(level_length):
                node = que.popleft()
                if node.left: que.append(node.left)
                if node.right: que.append(node.right)
        return res

429. N 叉树的层序遍历

注意在N叉树的链式存储中,node.children指向的是一个list。

from collections import deque
class Solution:
    def levelOrder(self, root: 'Node') -> List[List[int]]:
        if not root: 
            return []

        res = []
        que = deque([root])

        while que:
            level_len = len(que)
            cur = []
            for _ in range(level_len):
                node = que.popleft()
                cur.append(node.val)

                for child in node.children:
                    que.append(child)
            res.append(cur)
        return res

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

from collections import deque
class Solution:
    def largestValues(self, root: Optional[TreeNode]) -> List[int]:
        if not root:
            return []
        
        queue = deque([root])
        result = []
        
        while queue:
            level_size = len(queue)
            level_nodes = []
            
            for _ in range(level_size):
                node = queue.popleft()
                level_nodes.append(node.val)
                
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
            
            result.append(max(level_nodes))
        
        return result

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

from collections import deque
class Solution:
    def connect(self, root: 'Optional[Node]') -> 'Optional[Node]':
        if not root:
            return root
        
        queue = deque([root])
        
        while queue:
            level_size = len(queue)
            level_nodes = []
            
            for _ in range(level_size):
                node = queue.popleft()
                level_nodes.append(node)
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
            level_nodes.append(None)
            for _ in range(level_size):
                level_nodes[_].next = level_nodes[_ + 1]
        return root

其实这个题不需要层序遍历,因为已经是完美二叉树,直接左孩子连右孩子,右孩子连next的左孩子即可:

class Solution:
    def connect(self, root: 'Optional[Node]') -> 'Optional[Node]':
        if not root:
            return None
        leftmost = root
        while leftmost.left:
            head = leftmost
            while head:
                head.left.next = head.right
                if head.next:
                    head.right.next = head.next.left
                head = head.next
            leftmost = leftmost.left

        return root

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

看了上一题的题解,优化一下上一题的写法。

from collections import deque
class Solution:
    def connect(self, root: 'Node') -> 'Node':
        if not root:
            return root
        
        que = deque([root])
        while que:
            level_size = len(que)
            for _ in range(level_size):
                node = que.popleft()
                if _ < level_size - 1:
                    node.next = que[0]
                if node.left: que.append(node.left)
                if node.right: que.append(node.right)
        return root

104. 二叉树的最大深度

from collections import deque
class Solution:
    def maxDepth(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0
        
        que = deque([root])
        res = 0
        while que:
            res += 1
            level_size = len(que)
            for _ in range(level_size):
                node = que.popleft()
                if node.left: que.append(node.left)
                if node.right: que.append(node.right)
        return res

111. 二叉树的最小深度

from collections import deque
class Solution:
    def minDepth(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0
        
        que = deque([root])
        res = 0
        while que:
            res += 1
            level_size = len(que)
            for _ in range(level_size):
                node = que.popleft()
                if not node.left and not node.right: return res
                if node.left: que.append(node.left)
                if node.right: que.append(node.right)
        return res

226. 翻转二叉树

*尝试递归实现:

终止条件:节点为空。递推式:交换翻转转好的左右子树。

看了代码随想录的详解,自己还真想半天才发现自己写的是好像什么遍历顺序都不是。。。根本没有想过遍历顺序这个问题。

自己写的递归实际上是从下往上交换的,与后序遍历类似,但是顺序上不一致。

class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root:
            return root
        
        root.left, root.right = self.invertTree(root.right), self.invertTree(root.left)
        return root

前序遍历:

前序遍历是从上往下交换的,是个尾递归。

class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root:
            return root
        
        root.left, root.right = root.right, root.left
        root.left = self.invertTree(root.left)
        root.right = self.invertTree(root.right)
        return root
class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root:
            return root
        
        stack = [root]
        while stack:
            node = stack.pop()
            node.left, node.right = node.right, node.left
            if node.right: stack.append(node.right)
            if node.left: stack.append(node.left)

        return root

后序遍历:

递归实现,交换前序遍历的顺序即可:

class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root:
            return root
        
        root.left = self.invertTree(root.left)
        root.right = self.invertTree(root.right)
        root.left, root.right = root.right, root.left
        return root

迭代实现:

class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root:
            return root
        
        stack = [root]
        while stack:
            node = stack.pop()
            if node.right: stack.append(node.right)
            if node.left: stack.append(node.left)
            node.left, node.right = node.right, node.left
        return root

中序遍历:

中序遍历递归实现时,本想简单地交换两行。但是这样结果是错误的,因为有的交换多进行了一次。

只要把中交换的下一行的递归输入值也交换一下就可以了。

class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root:
            return root
        
        root.left = self.invertTree(root.left)
        root.left, root.right = root.right, root.left
        root.right = self.invertTree(root.left) #这里需要处理一下,因为中间节点已经交换过了,递归下一轮也要换一下,否则会重复
        return root

迭代实现:

class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root:
            return root
        
        stack = [root]
        while stack:
            node = stack.pop()
            if node.right: stack.append(node.right)
            node.left, node.right = node.right, node.left
            if node.left: stack.append(node.right)
        return root

复习一下迭代统一实现:

class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root:
            return root
        
        stack = [root]
        while stack:
            node = stack.pop()
            if node:
                if node.right: stack.append(node.right)
                stack.append(node)
                stack.append(None)
                if node.left: stack.append(node.left)
            else:
                node = stack.pop()
                node.left, node.right = node.right, node.left
        return root

层序遍历:

class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root:
            return root
        
        que = collections.deque([root])
        while que:
            level_size = len(que)
            for _ in range(level_size):
                node = que.popleft()
                if node.left: que.append(node.left)
                if node.right: que.append(node.right)
                node.left, node.right = node.right, node.left
        return root

101. 对称二叉树

递归实现:

递归最神奇的一点是isMirror最后一行可以不去判断left.val == right=val!想了半天,其实是因为not left or not right or left.val != right.val的逆命题是left and right and left.val == right.val即终止条件已经判断过这俩的值相等了。

class Solution:
    def isSymmetric(self, root: Optional[TreeNode]) -> bool:
        if not root:
            return True
        return self.isMirror(root.left,root.right)
        
    def isMirror(self, left, right):
        #终止条件:两个都是空或者return False
        if not left and not right: return True
        elif not left or not right or left.val != right.val: return False

        #递归进行判断
        return self.isMirror(left.left, right.right) and self.isMirror(left.right, right.left)

迭代实现:

class Solution:
    def isSymmetric(self, root: Optional[TreeNode]) -> bool:
        if not root:
            return True
        
        stack = [root.left,root.right]
        while stack:
            r = stack.pop()
            l = stack.pop()
            if not r and not l:
                continue
            elif (not r and l) or (r and not l) or (r and l and r.val != l.val):
                return False

            stack.append(l.left)
            stack.append(r.right)
            stack.append(l.right)
            stack.append(r.left)
        return True

理解迭代代码的关键还是刚刚所说的not left or not right or left.val != right.val的逆命题是left and right and left.val == right.val

只有满足left和right都存在且相等时,向que或者stack里面继续压下一对值。

这题居然是easy,真难顶

今日总结:

内容好多啊!!有点绕进去了,又好像理解了????

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值