同时遍历两个二叉树的题目采用的模板风格统一,较为直观简单
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