刷题笔记 -LeetCode 相同的树

LeetCode 100 相同的树

题目

给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例 1
输入:p = [1,2,3], q = [1,2,3]
输出:true
在这里插入图片描述

分析

可以对本题进行分解,分为三个方面进行比较:
p树的根节点和q树的根节点进行比较
p树的左子树和q树的左子树进行比较
p树的右子树和q树的右子树进行比较
比较示例

递归法

实现递归,需要两步:
找出重复子问题(递推公式):
终止条件

①重复子问题

由上图可知
p的左子树和q的左子树是否相等,p的右子树和q的右子树是否相等

相等就返回True,不相等返回False

#判断两颗二叉树的左,右子树是否相等
        leftTree = self.isSameTree(p.left,q.left)
        rightTree = self.isSameTree(p.right,q.right)
        

②确定终止条件

这道题涉及到比较节点的值是否相等,涉及情况需要分类讨论。

1)首先根节点为空的情况,分为三种情况
  • p,q的根节点均为空,两者都是空树,那么两棵树显然相同
  • p的根节点为空,q的根节点不为空,两棵树不相同
  • p的根节点不为空,q的根节点为空,两棵树不相同
2)两者根节点不为空的情况
  • 比较p,q根节点的值,如果不相等,那么两棵树不相同

Python代码实现

# 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 isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
        if p==None and q==None:
            return True
        if (p==None and q != None) or (p !=None and q==None):
            return False
        if p.val != q.val:
            return False
        leftTree = self.isSameTree(p.left,q.left)
        rightTree=self.isSameTree(p.right,q.right)
        
        ans=leftTree and rightTree

        return ans

假设 p 树有 n 个节点,q 树有 m 个节点。

不管是 p 和 q 树是否相同,都会遍历一遍节点少的树的所有节点,所以时间复杂度为 O(min(n,m))。

递归过程中,调用栈进行了入栈和出栈,所以空间复杂度为 O(min(n,m))。

非递归法(迭代)

这道题目,就是对于每一层来说,只要p树和q树的对应节点存在且相等即可
类似于层序遍历,使用队列来解决

每次将p树和q树对应层的节点依次入队列,p的左节点和q的左节点,p的右节点和q的右节点,进入队列

首先初始化队列,并将 p 树和 q 树的根节点入队列。
在这里插入图片描述

#初始化队列
queue = [p, q]

当队列不为空,将队列前两个元素出队列进行比较

在这里插入图片描述

		#队列中取出两个点进行比较
       p_node=queue.pop(0)
       q_node=queue.pop(0)
       #如果当前节点为空,则继续循环
       if p_node == None and q_node==None:
           continue
       #如果两者一个节点为空,另一个不为空,则一定不相同
       elif (p_node == None and q_node != None) or (p_node !=None and q_node == None):
           return False
        #如果两个节点都不为空,但节点值不相同,一定不相同
       elif p_node.val != q_node.val:
           return False
          

最后 下面再依次将 p 的左子树和 q 的左子树,p 的右子树和 q 的右子树入队列。

进行循环,出队列,比较,入队列,直到队列为空结束循环

Python 代码实现

# 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 isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
        queue=[p,q]
        while queue:
            p_node=queue.pop(0)
            q_node=queue.pop(0)
            if p_node == None and q_node==None:
                continue
            elif (p_node == None and q_node != None) or (p_node !=None and q_node == None):
                return False
            elif p_node.val != q_node.val:
                return False
            queue.append(p_node.left)
            queue.append(q_node.left)

            queue.append(p_node.right)
            queue.append(q_node.right)
        return True

对于迭代法,时间复杂度为 O(min(n,m)),空间复杂度为 O(min(n,m))。


总结

两种思路均是在某些方面做加减法,只是思维方式不一致
递归法是分解问题,根问题分解为子问题,最后自下而上解决。
迭代法是遍历问题,将问题遍历一遍,自顶向下解决。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值