二叉树相同的树
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))。
总结
两种思路均是在某些方面做加减法,只是思维方式不一致
递归法是分解问题,根问题分解为子问题,最后自下而上解决。
迭代法是遍历问题,将问题遍历一遍,自顶向下解决。