力扣Day15(2.15)| 第六章 二叉树 (层序遍历 226.翻转二叉树 101. 对称二叉树)

题一:

链接

题目链接:一题十杀
视频链接:
文章链接:

视频总结

关键点

  1. 使用队列实现,一套模板解决十个

力扣实战

①102. 二叉树的层序遍历

思路一:
 # Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        from collections import deque
        que = deque() # # 创建队列 便于层序操作
        result =[]  # 记录最终结果,二维数组,每个元素是一维数组
        if root != None:    # root 不是空时才加入队列 # if not root:写法也可
            que.append(root)
        while len(que)!=0:  # 队列不为空,用长度来写,若用!= None,会超时,在一轮外层循环后队列为空,说明all儿子讨论完了 # while que:
            size = len(que) # 记录当前层的节点数,否则不知道需要弹出队列里的多少个数至当前层的vector
            vector = [] # 记录每一层的节点的值
            while size: # 此时前面的循环执行了,所以size一定大于零,size等于零时说明当前层的数遍历完了
                node = que.popleft() # 弹出当前节点
                size -= 1
                vector.append(node.val) # 数值取出
                if node.left != None: # 因为用数组模拟队列,所以先加入右儿子,这样可以先pop左儿子
                    que.append(node.left)
                if node.right != None:
                    que.append(node.right)
            result.append(vector) 
        return result
        
# 反思1:
思路二:
 # Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
        # 递归法
        res = []
        def func(cur,depth): # depth 用于记录深度,也用于记录res里每一层的索引
            if not cur:
                return[]
            if len(res)==depth:
                res.append([])
            res[depth].append(cur.val)
            if cur.left:
                func(cur.left,depth+1)
            if cur.right:
                func(cur.right,depth+1)
            return res
        func(root,0)
        return res

②107. 二叉树的层序遍历 II

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def levelOrderBottom(self, root: Optional[TreeNode]) -> List[List[int]]:
        # 思路:对102题翻转一下
        res = []
        def func(cur,depth):
            if not cur:
                return []
            if len(res)==depth: # 这一行if必须加上,否则在结尾处会多两个[],因为当左儿子递归时,res已经有depth+1个了,此时还是这么多层,在递归右儿子时不需要在多加一个空格
                res.append([])
            res[depth].append(cur.val)
            if cur.left:
                func(cur.left,depth+1)
            if cur.right:
                func(cur.right,depth+1)
            return res
        func(root,0)
        res.reverse()
        return res

③199.二叉树的右视图

法一
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
        # 思路,层序递归遍历,稍作改动即可
        res=[]
        def func(cur,depth):
            if not cur:
                return []
            if len(res) == depth:
                res.append(0)   # res为一维数组,于是无需传入数组,而是传入一个数值占位置,否则后面无法索引到
            res[depth] = cur.val    #这里既是深度,也是res里每一层的那个数的索引,每次把每层vector里的最后一个元素传入res里,递归就是不是append,而是赋值
            if cur.left:
                func(cur.left,depth+1)
            if cur.right:
                func(cur.right,depth+1)
            return res
        func(root,0)
        return res

法二
	#每一层的点都放进去,然后取这一层的最后一个赋值
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
        if not root:
            return []
        # deque来自collections模块,不在力扣平台时,需要手动写入
        # 'from collections import deque' 导入
        # deque相比list的好处是,list的pop(0)是O(n)复杂度,deque的popleft()是O(1)复杂度

        quene = deque([root])
        out_list = []

        while quene:
            # 每次都取最后一个node就可以了
            node = quene[-1]
            out_list.append(node.val)

            # 执行这个遍历的目的是获取下一层所有的node
            for _ in range(len(quene)):
                node = quene.popleft()
                if node.left:
                    quene.append(node.left)
                if node.right:
                    quene.append(node.right)
        
        return out_list

④637.二叉树的层平均值

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def averageOfLevels(self, root: Optional[TreeNode]) -> List[float]:
    # """二叉树层平均值迭代解法"""
        results = []
        if not root:
            return results  
                  
        from collections import deque
        que = deque([root])
        
        while que:  
            size = len(que) 
            sum_ = 0    #直接也不储存了,直接sum一下 
            for _ in range(size):   # 只是改变了次数的遍历
                cur = que.popleft() 
                sum_ += cur.val
                if cur.left:
                    que.append(cur.left)
                if cur.right:
                    que.append(cur.right)
            results.append(sum_ / size) # 此时体现除了for写法的好处,没有改变size的大小

        return results

文档总结

1. deque里的append和extend?二叉树用append,n茶树用extend附加节点
2. 116117填充每个节点的下一个右侧节点指针,这一题有点难度,可能做不粗来。

题二:226.翻转二叉树

链接

题目链接:
视频链接:
文章链接:

视频总结

关键点

编程思路

卡尔:递归三部曲
  1. 确定返回值和参数。分别是TreeNode和root
  2. 终止条件:遇到空时终止
  3. 确定递归顺序 :前后都可,中有点麻烦,若选择前序,也即是前中后,其中前后是递归,中是操作的语句

力扣实战

思路一:

# 递归法有前中后三种顺序,前后只是调整语句的顺序,而中需要改掉后递归的儿子
 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
        
# 反思1:

思路二:

 # 迭代法指深度优先、广度优先。
 # 	深度前序
 class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        if not root:
            return root
        st = []
        st.append(root)
        while st:
            node = st.pop()
            node.left, node.right = node.right, node.left #中
            if node.right:
                st.append(node.right) #右
            if node.left:
                st.append(node.left) #左
        return root

#	广度 
import collections
class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        queue = collections.deque() #使用deque()
        if root:
            queue.append(root)
        while queue:
            size = len(queue)
            for i in range(size):
                node = queue.popleft()
                node.left, node.right = node.right, node.left #节点处理
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
        return root

文档总结

1. 针对二叉树的问题,解题之前一定要想清楚究竟是前中后序遍历,还是层序遍历。

二叉树解题的大忌就是自己稀里糊涂的过了(因为这道题相对简单),但是也不知道自己是怎么遍历的。

这也是造成了二叉树的题目“一看就会,一写就废”的原因。

题三:101. 对称二叉树

链接

题目链接:
视频链接:
文章链接:

视频总结

关键点

  1. 了解其遍历顺序:需要收集所有的孩子的信息返还给上一个节点时,则只能够使用后续遍历
  2. 考察同时处理两个二叉树的过程
  3. 原题意等价于判断对称二叉树也就是判断左右孩子是否可以翻转
  4. 单层递归的逻辑,单层递归的逻辑就是处理 左右节点都不为空,且数值相同的情况。

编程思路

Me:
卡尔:

力扣实战

思路一:

 class Solution:
    def isSymmetric(self, root: Optional[TreeNode]) -> bool:
        # 在初步学习的时候不要过于追求所谓简洁的代码,代码越简洁,就会漏掉很多的细节,这对初学者来说是很坏的情况
        if not root:
            return True
        return self.compare(root.left, root.right)
        
    def compare(self, left, right):
        #首先排除空节点的情况
        if left == None and right != None: return False
        elif left != None and right == None: return False
        elif left == None and right == None: return True
        #排除了空节点,再排除数值不相同的情况
        elif left.val != right.val: return False
        
        #此时就是:左右节点都不为空,且数值相同的情况
        #此时才做递归,做下一层的判断
        outside = self.compare(left.left, right.right) #左子树:左、 右子树:右
        inside = self.compare(left.right, right.left) #左子树:右、 右子树:左
        isSame = outside and inside #左子树:中、 右子树:中 (逻辑处理)
        return isSame     
        
        
# 反思1:

文档总结

1. 在初步学习的时候不要过于追求所谓简洁的代码,代码越简洁,就会漏掉很多的细节,这对初学者来说是很坏的情况
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二叉树层序遍历是一种广度优先搜索算法,通过逐层地从左到右访问所有节点,返回节点值的顺序。可以使用队列来实现层序遍历。具体思路如下: 1. 创建一个空的结果数组res和一个队列que,将根节点root放入队列que中。 2. 当队列que不为空时,执行以下操作: - 定义一个变量size,用于记录队列que的长度。 - 创建一个空的一维数组vec,用于记录当前层的节点值。 - 遍历0到size-1,执行以下操作: - 弹出队列que的头节点cur。 - 将cur的值cur->val添加到一维数组vec中。 - 若cur的左子节点不为空,则将cur的左子节点压入队列que中。 - 若cur的右子节点不为空,则将cur的右子节点压入队列que中。 - 将一维数组vec添加到结果数组res中。 3. 返回结果数组res作为层序遍历的结果。 以下是一段C++代码示例,实现了二叉树层序遍历: ``` vector<vector<int>> levelOrder(TreeNode* root) { vector<vector<int>> res; // 结果数组 queue<TreeNode*> que; if (root) que.push(root); while (!que.empty()) { int size = que.size(); // 记录队列的长度 vector<int> vec; for (int i = 0; i < size; i++) { TreeNode* cur = que.front(); que.pop(); vec.push_back(cur->val); if (cur->left) que.push(cur->left); if (cur->right) que.push(cur->right); } res.push_back(vec); } return res; } ``` 这段代码使用了一个队列que,利用队列的先进先出的特点,按照层序遍历的顺序将节点添加到结果数组res中。最后返回结果数组res即可得到二叉树层序遍历结果。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [力扣刷题 | 二叉树](https://download.csdn.net/download/weixin_38633083/13740772)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [力扣:102. 二叉树层序遍历](https://blog.csdn.net/qq_46111138/article/details/124895548)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值