leetcode分类刷题:二叉树(五、同时遍历两个二叉树)

同时遍历两个二叉树的题目采用的模板风格统一,较为直观简单

101. 对称二叉树

重复逻辑:两个二叉树同时遍历,同时比较前一个二叉树的左子树与后一个二叉树的右子树是否相等 及 前一个二叉树的右子树与后一个二叉树的左子树是否相等

'''
101. 对称二叉树
给你一个二叉树的根节点 root , 检查它是否轴对称。
示例 1:
    输入:root = [1,2,2,3,4,4,3]
    输出:true
题眼:对称二叉树,看着像是“226. 翻转二叉树”的类似题目,但其实不是;它们的区别在于对称二叉树是两个二叉树进行对比,同时对称二叉树是带返回值的递归。
思路一:递归遍历,两个二叉树同时遍历,同时比较前一个二叉树的左子树与后一个二叉树的右子树是否相等 及 前一个二叉树的右子树与后一个二叉树的左子树是否相等
思路二:迭代遍历-队列/栈,以队列为例(不是层序遍历),初始化为左右子树,依次出队两个左右节点进行比较,再将两个节点的左右子树按照镜像比较的顺序入队
'''
class Solution:
    # 递归法
    def isSymmetric(self, root: Optional[TreeNode]) -> bool:
        if root == None:
            return True
        # 1、确定递归函数的参数和返回值
        def compare(p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
            # 2、终止条件:最简单情况
            if p == None and q == None:
                return True
            elif p == None and q != None:
                return False
            elif p != None and q == None:
                return False
            elif p.val != q.val:
                return False
            else:  # 3、确定单次递归的操作
                return compare(p.left, q.right) and compare(p.right, q.left)
        return compare(root.left, root.right)
    
    # 迭代法-队列
    def isSymmetricIteration(self, root: Optional[TreeNode]) -> bool:
        if root == None:
            return True
        dq = deque()
        dq.append(root.left)  # 初始化为左右子树
        dq.append(root.right)
        while len(dq) > 0:
            # 总是同时 比较前一个二叉树的左子树与后一个二叉树的右子树是否相等 及 前一个二叉树的右子树与后一个二叉树的左子树是否相等
            p = dq.popleft()
            q = dq.popleft()
            if p == None and q == None:
                continue
            elif p == None and q != None:
                return False
            elif p != None and q == None:
                return False
            elif p.val != q.val:
                return False
            else:
                # 先添加前一个二叉树的左子树与后一个二叉树的右子树
                dq.append(p.left)
                dq.append(q.right)
                # 再添加前一个二叉树的右子树与后一个二叉树的左子树
                dq.append(p.right)
                dq.append(q.left)
        return True

100. 相同的树

重复逻辑:两个二叉树同时遍历,同时比较前一个二叉树的左子树与后一个二叉树的左子树是否相等 及 前一个二叉树的右子树与后一个二叉树的右子树是否相等

'''
100. 相同的树
给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
示例 1:
    输入:p = [1,2,3], q = [1,2,3]
    输出:true
题眼:“101. 对称二叉树” 的相似题目
'''
class Solution:
    def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
        # 重复逻辑:同时比较两个二叉树的左右子树是否对应相同
        # 递归终止条件:简单情况
        if p == None and q == None:
            return True
        elif p == None and q != None:
            return False
        elif p != None and q == None:
            return False
        elif p.val != q.val:
            return False
        else:  # 递归操作:重复逻辑
            return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)

    # 迭代法-队列
    def isSameTreeIteration(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
        # 因为是两颗子树的相等性判断问题,不用一开始判断树是否为空的问题
        dq = deque()
        dq.append(p)  # 初始化为两颗子树
        dq.append(q)
        while len(dq) > 0:
            # 总是同时 比较前一个二叉树的左子树与后一个二叉树的左子树是否相等 及 前一个二叉树的右子树与后一个二叉树的右子树是否相等
            t1 = dq.popleft()
            t2 = dq.popleft()
            if t1 == None and t2 == None:
                continue
            elif t1 == None and t2 != None:
                return False
            elif t1 != None and t2 == None:
                return False
            elif t1.val != t2.val:
                return False
            else:
                # 先添加前一个二叉树的左子树与后一个二叉树的左子树
                dq.append(t1.left)
                dq.append(t2.left)
                # 再添加前一个二叉树的右子树与后一个二叉树的右子树
                dq.append(t1.right)
                dq.append(t2.right)
        return True

572. 另一棵树的子树

先把root进行前序遍历:用迭代循环遍历的方式更好理解;接着调用重复逻辑:两个二叉树同时遍历,同时比较前一个二叉树的左子树与后一个二叉树的左子树是否相等 及 前一个二叉树的右子树与后一个二叉树的右子树是否相等

'''
572. 另一棵树的子树
给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。
二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。
示例 1:
    输入:root = [3,4,5,1,2], subRoot = [4,1,2]
    输出:true
题眼:"100. 相同的树" 的相似题目
思路:(前序)迭代法遍历root+迭代法-两棵树是否相等;
'''
class Solution:
    def isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool:
        # 把判断相同的树的逻辑当成一个函数去调用
        def isSame(p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
            # 简单逻辑
            if p == None and q == None:
                return True
            elif p == None and q != None:
                return False
            elif p != None and q == None:
                return False
            elif p.val != q.val:
                return False
            else:  # 递归操作:重复逻辑
                return isSame(p.left, q.left) and isSame(p.right, q.right)
        # 把root进行前序遍历:用迭代循环遍历的方式更好理解
        stk = [root]
        while len(stk) > 0:
            cur = stk.pop()
            if cur.val == subRoot.val:
                if isSame(cur, subRoot):
                    return True
            if cur.right != None:
                stk.append(cur.right)  # 先右后左入栈,出栈才是 根左右 的遍历
            if cur.left != None:
                stk.append(cur.left)
        return False

617. 合并二叉树

递归重复逻辑:不断构造合并后的二叉树根节点、左子树、右子树

'''
617. 合并二叉树
给你两棵二叉树: root1 和 root2 。
想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。
合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。
返回合并后的二叉树。
注意: 合并过程必须从两个树的根节点开始。
示例 1:
    输入:root1 = [1,3,2,5], root2 = [2,1,3,null,4,null,7]
    输出:[3,4,5,5,4,null,7]
题眼:同时操作两个二叉树
思路:递归重复逻辑:不断构造合并后的二叉树根节点、左子树、右子树
'''
class Solution:
    def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
        # 简单情况
        if root1 == None and root2 == None:
            return None
        elif root1 != None and root2 == None:
            return root1
        elif root1 == None and root2 != None:
            return root2
        else:  # 重复逻辑:不断构造合并后的二叉树根节点、左子树、右子树
            root = TreeNode(root1.val + root2.val)
            root.left = self.mergeTrees(root1.left, root2.left)
            root.right = self.mergeTrees(root1.right, root2.right)
            return root
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

22世纪冲刺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值