一套模板搞定二叉树算法题--二叉树算法讲解001

1、二叉树定义

mark

2、二叉树存储结构

mark

2.1、经典题目代码构建

mark

代码构建:
mark

代码对应的二叉树的图:
mark

一行代码搞定lettcode2236,运行通过;就是考察对二叉树结构的理解:
mark

3、深度优先遍历DFS和广度优先遍历BFS概念

mark

3.1、深入讲解广度优先遍历BFS

mark

树的 广度优先遍历BFS 也可以称之为层序遍历

mark

广度优先遍历BFS与队列Queue的关系图:
mark

队列基础知识
mark

结合队列基础知识中对于popleft()函数的讲解,会发现上面的 广度优先遍历BFS与队列Queue的关系图
在绘制时,左右方向上可能搞反了,不太容易理解。

所以重新绘制一个左右方向容易理解的版本的广度优先遍历BFS与队列Queue的关系图 :
mark

4、万能模板经典题

mark

4.1、LeetCode102

mark

mark

mark

mark

4.2、LeetCode107

和102题相同的模板,代码几乎相同,只需要在最后一行用切片的写法做一个反转即可:
mark

4.3、LeetCode103

题目:
mark

题意:
mark

题解:
只需要在模板的基础上,添加一个Flag标志,标记从左往右或者从右往左即可。
mark

4.4、LeetCode637

这连续几道题,都提到二叉树的 的概念,就可以很明显的考虑到是要用层序遍历 来做。
题目:
mark

题意:
mark

题解:
基于模板,最后添加元素处改一下,由添加层列表,即(每一层的所有节点),改为添加每一层所有节点的平均值即可。
mark

4.5、LeetCode199

题目:
mark

题意:
mark

题解:
根据题意,实际上这道题问的是每一的最右边的元素是什么?
所以还是涉及到的概念,还是要用层序遍历 来做。然后再每一层取出最右边的元素即可。

基于模板,只改一下最后的添加,由添加层列表,改为添加每一层的最后一个元素即可。
mark

如果不用模板,不用层列表sublist,也可以修改为如下代码:
mark
这样就不用额外的空间去存每一层的所有节点。只在每一层的最后一个节点去判断,然后添加最后一个节点到总的列表。

这道题,不是一个明显的层序遍历的题,但是仔细分析题意,思路转换,还是能结合层序遍历模板来解题的。

4.6、LeetCode513

题目和题意:
mark

题解:
基于模板,只需要改动最终的返回ans,ans的初始化由初始化为list改为初始化为root.val,即初始化为根节点的值。
ans的返回由添加层列表,改为添加层的左侧第一个元素的值。
mark

考虑内存空间的情况,可以进一步优化为如下代码:
1和2都可以解决问题
1、
mark
2、
mark

mark

4.7、LeetCode515

题目和题意:
mark

题解:
模板改最后一行添加层列表的最大值即可。
mark

4.8、LeetCode1161

题目和题意:
这个题目还是需要仔细读一下的:
mark

题解:
1、先解决层号的问题,输出层号
mark

mark

2、题解完成:
mark

考虑到节点值可能为负数的情况,最大层的和level_max_sum的初始化,由初始化为0改为初始化为负无穷-inf或者初始化为第一层的值root.val
mark

mark

对题解优化,尽量不要用标准sum函数api,因为它每次也要全部遍历,比较耗时。
不用sum函数的修改版:
mark

4.9、LeetCode101

题目和题意:
示例1
mark
示例2
mark

题解:
1、
mark

2、题解1中还是有问题,满足示例1图的情况,但是不满足示例2;
修改为如下代码后,同时满足示例1和示例2
mark

4.10、LeetCode1302

题目:
mark

题意:
最深的那层这里就是第四层的7和8、最深的那层的节点就一定是叶子节点。

mark

mark

题解:
修改 4.6、LeetCode513 中的代码,将找左下角节点的值,改为求和即可。
mark

不用sum函数的优化版:
mark

5、总结

最核心知识点:
BFS与队列的关系
mark
mark

leetcode102题引申出的万能模板:
mark

mark

模板代码及测试

from collections import deque
from typing import List

class TreeNode:
    def __init__(self,val=0,left=None,right=None):
        self.val = val
        self.left = left
        self.right = right

def levelOrder(root) -> List[List[int]]:
        # if root is None:
        # if root == None:
        if not root:
            return []
        ans = list()
        q = deque()
        q.append(root)
        # while len(q) > 0:
        # while len(q):
        while q:
            qSize = len(q)
            subList = list()
            # for i in range(qSize):
            for _ in range(qSize):
                node = q.popleft()
                subList.append(node.val)
                # if node.left != None:
                if node.left:
                    q.append(node.left)
                # if node.right != None:
                if node.right:
                    q.append(node.right)
            ans.append(subList)
        return ans

if __name__ == '__main__':
    root = TreeNode(1)
    root.left = TreeNode(2)
    root.right = TreeNode(3)
    root.left.left = TreeNode(4)
    root.left.right = TreeNode(5)
    root.right.left = TreeNode(6)
    root.right.right = TreeNode(7)
    root.left.left.left = TreeNode(8)
    result = levelOrder(root)

    # 打印结果
    print(result)

6、练习题

mark


注:
文中截图源自大佬: 闭着眼睛学数理化 课程内容

posted @ 2024-01-06 12:27  皿哥的技术人生  阅读(113)  评论(0编辑  收藏  举报