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

102. 二叉树的层序遍历

题目描述: 102. 二叉树的层序遍历.

解法

层级法
class Solution(object):
    def levelOrder(self, root):
        if not root:
            return []
        res = []
        st = collections.deque([root])
        while st:
            level = []
            for _ in range(len(st)):
                node = st.popleft()
                level.append(node.val)
                if node.left:
                    st.append(node.left)
                if node.right:
                    st.append(node.right)
            res.append(level)
        return res

主要思想就是根据st的数量,向res中添加内容,并根据当前层向st加入node,这样每一次遍历st就都是这一层应有的node数量

递归
class Solution(object):
    def leveltravel(self,node,level,res):
        if not node:
            return 
        if len(res) == level:
            res.append([])
        res[level].append(node.val)
        self.leveltravel(node.left,level+1,res)
        self.leveltravel(node.right,level+1,res)
        
    def levelOrder(self, root):
        res = []
        self.leveltravel(root,0,res)
        return res

递归的方法就是找共性,共性就是每个节点都有子节点,然后想找每一层的输出,他们的层数就是一样的,层数就对应着res的长度-1,只要左在前,每一层遍历的时候都一定会从左到右进行遍历,通过层数来控制插入值的位置,这样就不用考虑遍历和插值操作的先后顺序了。

107.二叉树的层次遍历 II

题目描述: 107.二叉树的层次遍历 II.

解法

层级法
class Solution(object):
    def levelOrderBottom(self, root):
        if not root:
            return []
        st = collections.deque([root])
        res = []
        while st:
            level = []
            for _ in range(len(st)):
                node = st.popleft()
                level.append(node.val)
                if node.left:
                    st.append(node.left)
                if node.right:
                    st.append(node.right)
            res.append(level)
        return res[::-1]
递归法
class Solution(object):
    def leveltravel(self,node,level,res):
        if not node:
            return
        if level == len(res):
            res.append([])
        res[level].append(node.val)
        self.leveltravel(node.left,level+1,res)
        self.leveltravel(node.right,level+1,res)

    def levelOrderBottom(self, root):
        res = []
        self.leveltravel(root,0,res)
        return res[::-1]

199.二叉树的右视图

题目描述: 199.二叉树的右视图.

解法

class Solution(object):
    def rightSideView(self, root):
        if not root:
            return []
        res = []
        st = collections.deque([root])
        while st:
            for _ in range(len(st)):
                node = st.popleft()
                if node.left:
                    st.append(node.left)
                if node.right:
                    st.append(node.right)
            res.append(node.val)
        return res

只需要输出每一层的最后一个就可以了
这道题好像不能用递归做

637.二叉树的层平均值

题目描述: 637.二叉树的层平均值.

解法

层级
class Solution:
    def averageOfLevels(self, root: Optional[TreeNode]) -> List[float]:
        if not root:
            return []
        st = collections.deque([root])
        res = []
        while st:
            sum = 0
            size = len(st)
            for _ in range(size):
                node = st.popleft()
                sum += node.val
                if node.left:
                    st.append(node.left)
                if node.right:
                    st.append(node.right)
            res.append(sum/size)
        return res
迭代
class Solution:
    def leveltravel(self,node,level,res):
        if not node:
            return 
        if len(res) == level:
            res.append([])
        res[level].append(node.val)
        self.leveltravel(node.left, level+1, res)
        self.leveltravel(node.right, level+1, res)

    def averageOfLevels(self, root: Optional[TreeNode]) -> List[float]:
        levels = []
        res = []
        self.leveltravel(root,0,levels)
        for level in levels:
            size = len(level)
            sum = 0
            for l in level:
                sum+=l
            res.append(sum/size)
        return res

429.N叉树的层序遍历

题目描述: 429.N叉树的层序遍历.

解法

层级遍历
class Solution(object):
    def levelOrder(self, root):
        if not root:
            return []
        res = []
        st = collections.deque([root])
        while st:
            level = []
            for _ in range(len(st)):
                node = st.popleft()
                level.append(node.val)
                for c in node.children:
                    st.append(c)
            res.append(level)
        return res
递归
class Solution(object):
    def leveltravel(self,node,level,res):
        if not node:
            return
        if level == len(res):
            res.append([])
        res[level].append(node.val)
        for child in node.children:
            self.leveltravel(child,level+1,res)
        
    def levelOrder(self, root):
        res = []
        self.leveltravel(root,0,res)
        return res

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

题目描述: 515.在每个树行中找最大值.

解法

class Solution(object):
    def largestValues(self, root):
        if not root:
            return []
        st = collections.deque([root])
        res = []
        while st:
            m = 0 - float('inf')
            for _ in range(len(st)):
                node = st.popleft()
                m = m if m > node.val else node.val
                if node.left:
                    st.append(node.left)
                if node.right:
                    st.append(node.right)
            res.append(m)
        return res

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

题目描述: 116.填充每个节点的下一个右侧节点指针.

解法

class Solution(object):
    def connect(self, root):
        if not root:
            return root
        st = collections.deque([root])
        while st:
            pre = None
            for _ in range(len(st)):
                node = st.popleft()

                if pre:
                    pre.next = node
                pre = node
                if node.left:
                    st.append(node.left)
                if node.right:
                    st.append(node.right)
        return root

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

题目描述: 117.填充每个节点的下一个右侧节点指针II.

解法

lass Solution(object):
    def connect(self, root):
        if not root:
            return root
        st = collections.deque([root])
        while st:
            pre = None
            for _ in range(len(st)):
                node = st.popleft()
                if pre:
                    pre.next = node
                pre = node

                if node.left:
                    st.append(node.left)
                if node.right:
                    st.append(node.right)
        return root

104.二叉树的最大深度

题目描述: 104.二叉树的最大深度.

解法

递归
class Solution(object):
    def leveltravel(self,node,level):
        if not node:
            return level
        return max(self.leveltravel(node.left,level+1),self.leveltravel(node.right,level+1))
        
    def maxDepth(self, root):
        return self.leveltravel(root,0)
层级迭代
class Solution(object):
    def maxDepth(self, root):
        if not root:
            return 0
        st = collections.deque([root])
        level = 0
        while st:
            level += 1
            for _ in range(len(st)):
                node = st.popleft()
                if node.left:
                    st.append(node.left)
                if node.right:
                    st.append(node.right)
        return level

111.二叉树的最小深度

题目描述: 111.二叉树的最小深度.

解法

递归(有问题)
class Solution(object):
    def travel(self,node,level):
        if not node:
            return level
        return min(self.travel(node.left,level+1),self.travel(node.right,level+1))
    def minDepth(self, root):
        return self.travel(root,0)
层级
class Solution(object):
    def minDepth(self, root):
        if not root:
            return 0
        st = collections.deque([root])
        level = 0
        while st:
            level+=1
            for _ in range(len(st)):
                node = st.popleft()
                if not (node.left or node.right):
                    return level
                if node.left:
                    st.append(node.left)
                if node.right:
                    st.append(node.right)
        return level

226.翻转二叉树 (优先掌握递归)

226.翻转二叉树

题目描述: 226.翻转二叉树.

解法

递归前序遍历
class Solution(object):
    def invertTree(self, root):
        if not root:
            return None
        root.right, root.left = root.left, root.right
        self.invertTree(root.left)
        self.invertTree(root.right)
        return root
迭代前序遍历
class Solution(object):
    def invertTree(self, root):
        if not root:
            return root
        st = [root]
        while st:
            node = st.pop()
            node.left,node.right = node.right,node.left
            if node.left:
                st.append(node.left)
            if node.right:
                st.append(node.right)
        return root

因为不需要访问具体的值,所以可以不用完全迭代

递归中序遍历
class Solution(object):
    def invertTree(self, root):
        if not root:
            return root
        self.invertTree(root.left)
        root.right, root.left = root.left, root.right
        self.invertTree(root.left)
        return root
迭代中序遍历
class Solution(object):
    def invertTree(self, root):
        st = []
        if root:
            st.append(root)
        while st:
            node = st.pop()
            if node.left:
                st.append(node.left)
            node.left, node.right = node.right, node.left
            if node.left:
                st.append(node.left)
        return root

先压到栈中的应该是将来的右节点,而left则会变成将来的右节点,所以无论是迭代还是递归,都应先处理left,再考虑后面的right是否已经更新。
在遍历中则只需要考虑左右即可

递归后序遍历
class Solution(object):
    def invertTree(self, root):
        if not root:
            return root
        self.invertTree(root.left)
        self.invertTree(root.right)
        root.right,root.left = root.left, root.right
        return root
迭代后序遍历
class Solution(object):
    def invertTree(self, root):
        st = []
        if root:
            st.append(root)
        while st:
            node = st.pop()
            if node.left:
                st.append(node.left)
            if node.right:
                st.append(node.right)
            node.left, node.right = node.right, node.left
        return root
层级
class Solution(object):
    def invertTree(self, root):
        if not root:
            return root
        que = collections.deque([root])
        while que:
            for i in range(len(que)):
                node = que.popleft()
                node.left,node.right = node.right, node.left
                if node.right:
                    que.append(node.right)
                if node.left:
                    que.append(node.left)
        return root

因为是层级,所以不需要考虑左右节点谁先进队列,如果要求读取顺序,则需要考虑谁先进

101.对称二叉树

题目描述: 101.对称二叉树 .

解法

递归
class Solution(object):
    def isSymmetric(self, root):
        if not root:
            return True
        return self.compare(root.left,root.right)

    def compare(self,left,right):
        if left and not right:
            return False
        elif not left and right:
            return False
        elif not left and not right:
            return True
        elif left.val != right.val:
            return False
        
        out_side = self.compare(left.left,right.right)
        in_side = self.compare(left.right,right.left)
        return out_side and in_side

递归到底要考虑什么?考虑的是什么是相同的,要继续往下走,而这道题就是需要用后序遍历,遍历的内容是两个节点是否相同,也可以说两棵树是否相同,那如果两个节点的值相同,他们的子节点就不一定相同,那么就还是要先遍历子节点。
递归首先考虑边界情况,什么时候就可以返回值了?第二要考虑在每次递归里都做什么,什么是重复的部分?第三是考虑递归返回的值到底是什么?这样一来就可以写好一个递归的内容了。

使用栈
class Solution(object):
    def isSymmetric(self, root):
        if not root:
            return True
        st = [root.left,root.right]
        while st:
            r_node = st.pop()
            l_node = st.pop()
            if not r_node and not l_node:
                continue
            if not r_node or not l_node or r_node.val != l_node.val:
                return False
            st.append(l_node.left)
            st.append(r_node.right)
            st.append(l_node.right)
            st.append(r_node.left)
        return True
使用队列
class Solution(object):
    def isSymmetric(self, root):
        if not root:
            return True
        que = collections.deque([root.left,root.right])
        while que:
            l_node = que.popleft()
            r_node = que.popleft()
            if not l_node and not r_node:
                continue
            if not l_node or not r_node or l_node.val != r_node.val:
                return False
            que.append(l_node.left)
            que.append(r_node.right)
            que.append(l_node.right)
            que.append(r_node.left)
        return True

无论是栈或者是队列,都是暂时储存左右两个节点的,每次取出两个节点,检查这两个节点的相同关系。

层次
class Solution(object):
    def isSymmetric(self, root):
        if not root:
            return True
        levels = []
        que = collections.deque([root.left,root.right])
        while que:
            level = []
            if len(que)%2!=0:
                return False
            for _ in range(len(que)):
                node = que.popleft()
                if node:
                    que.append(node.left)
                    que.append(node.right)
                    level.append(node.val)
                else:
                    level.append(None)
            levels.append(level)
        for level in levels:
            if level != level[::-1]:
                return False
        return True

因为考虑到要看左右是否对称,因此就算节点是空的也要加到队列中,然后拿出每一层的节点是否和其反序相同。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值