LeetCode 剑指Offer 数据结构之 树 总结 Part2

LeetCode 剑指Offer 数据结构之 树 总结 Part2

经典问题

1)遍历
2)树深度
3)重建树
4)对称树
5)子树匹配
6)二叉查找树

遍历问题 补充
DFS(一般采用递归) 深度优先的遍历
在此补充非递归方式的三种遍历

先序遍历:

def bin_tree_pre_order_traverse1(root):
    '''
    利用1个栈实现
    '''
    res = []
    s1 = []
    s1.append(root)
    while s1:
        node = s1.pop()# 对于s1中每个要被访问的跟节点
        res.append(node.val)# 先访问它本身(根)
        # 压栈 右,左->下次循环时出栈 左 右,符合前序遍历
        if node.right:
            s1.append(node.right)
        if node.left:
            s1.append(node.left)
    return res

中序遍历:

def bin_tree_in_order_traverse1(root):
    '''
    利用1个栈实现
    '''
    res = []
    s1 = []
    node = root# 根节点先不入栈 需要找到最左的节点
    while node or s1:
        if node:
            s1.append(node)
            node = node.left# 向左不停找
        else:
            # node 为空,走到叶子节点了
            node = s1.pop()# 左边节点的根(最左节点)
            res.append(node.val)# 入栈
            node = node.right
    return res

后序遍历:

def bin_tree_post_order_traverse1(root):
    '''
    利用两个栈实现
    '''
    s1 = []
    s2 = []
    s1.append(root)
    res = []
    while s1:
        node = s1.pop()
        s2.append(node)# 中进栈 右进栈 左进栈
        if node.left:
            s1.append(node.left)
        if node.right:
            s1.append(node.right)
    while s2:# 反过来 左出,右出,中出
        res.append(s2.pop().val)
    return res
深度问题

对应题目编号:
剑指 Offer 55 - I
剑指 Offer 55 - II

求二叉树深度:

class Solution:
    def maxDepth_DFS(self, root):
        if not root:
            return 0
        return max(self.maxDepth_DFS(root.left), self.maxDepth_DFS(root.right)) + 1

    def maxDepth_BFS(self, root):
        if not root:
            return 0
        queue = [root]
        res = 0
        while queue:
            tmp = []
            for index in range(len(queue)):
                nodei = queue[index]
                if nodei.left:
                    tmp.append(nodei.left)
                if nodei.right:
                    tmp.append(nodei.right)
            queue = tmp  # 转移到下一层
            res += 1
        return res

DFS的方式:通过递归达到底部叶子节点,从0开始返回开始计数!
树的深度是每一颗子树的左右根的深度最大值+1

BFS的方式:
特例处理: 当 root​ 为空,直接返回 深度 00 。
初始化: 队列 queue (加入根节点 root ),计数器 res = 0。
循环遍历: 当 queue 为空时跳出。
初始化一个空列表 tmp ,用于临时存储下一层节点;
遍历队列: 遍历 queue 中的各节点 node ,并将其左子节点和右子节点加入 tmp;
更新队列: 执行 queue = tmp ,将下一层节点赋值给 queue;
统计层数: 执行 res += 1 ,代表层数加 11;
返回值: 返回 res 即可。

判断是否是平衡树

class Solution:
    def isBalanced(self, root):
        def recur(root):
            if not root:  # 出口
                return 0  # 正常递归穿过叶子节点 作为递归到底部叶子节点 开始计算深度 从0开始 特例空树也在这里
            left = recur(root.left)
            if left == -1:  # 出口
                return -1
            right = recur(root.right)
            if right == -1:  # 出口
                return -1
            return max(left, right) + 1 if abs(left - right) <= 1 else -1

        return recur(root) != -1

后序遍历 + 剪枝 (从底至顶)
思路是对二叉树做后序遍历,从底至顶返回子树深度,若判定某子树不是平衡树则 “剪枝” ,直接向上返回
总结:主要分几种情况可以触发剪枝
1:当节点root 左 / 右子树的深度差 > 2 :则返回 -1 不是平衡树
2:当左(右)子树深度为 -1 :代表此树的 左(右)子树 不是平衡树,因此剪枝,直接返回 -1

下一部分将继续总结重建树内容

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值