【树】力扣101:对称二叉树
给你一个二叉树的根节点 root , 检查它是否轴对称。
示例:
输入:root = [1,2,2,3,4,4,3]
输出:true
判断一个树是否对称 等价于 判断左右子树是否镜像对称。因此,该问题可以转化为:两个树在什么情况下互为镜像?
如果同时满足下面的条件,两个树互为镜像:
-
它们的两个根结点具有相同的值
-
每个树的右子树都与另一个树的左子树镜像对称
递归
递归解法主要考虑递归终止条件:
-
两个结点都为空
-
两个结点只有一个为空
-
两个结点的值不相等
对应叫做 “四步法”,先看结点是否为空,再看树的结点的值:
-
如果两个结点都为空指针,则子树相等或对称
-
如果两个结点只有一个为空指针,则子树不相等或不对称
-
左结点和右结点都不为空则观察结点的值。如果两个子树的根结点的值不相等,则它们不相等或不对称
-
递归比较 left.left 与 right.right、left.right 与 right.left
![image]()
考虑特殊情况:
-
边界——树为空 root == None:对称,返回True
-
树不为空但只有一个根结点 not left and not right:对称,返回True(主函数中没有定义left和right,所以应写为root.left和root.right)
# 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 isSymmetric(self, root: Optional[TreeNode]) -> bool:
def helper(left, right):
# 左右结点都为空指针,则它们对称
if not left and not right:
return True
# 左右结点只有一个为空指针,则它们不对称
if (not left and right) or (not right and left):
return False
# 以下详细实现 return left.val != right.val and helper(left.left, right.right) and helper(left.right, right.left)
# 左结点和右结点都不为空则观察结点的值:两个子树的根结点的值不相等,则它们不对称
if left.val != right.val:
return False
return helper(left.left, right.right) and helper(left.right, right.left) # 比较 left.left 与 right.right,以及 left.right 与 right.left
# 用递归函数比较根结点的左右结点
return True if not root or not (root.left or root.right) else helper(root.left, root.right) # root == None 时树为空,直接判断对称,只有 root 时也直接判断对称,均不需递归比较
时间复杂度:这里遍历了这棵树,渐进时间复杂度为 O(n),其中 n 为树的结点数量。
空间复杂度:这里的空间复杂度和递归使用的栈空间有关,这里递归层数不超过 n,故渐进空间复杂度为 O(n)。
迭代
引入一个【队列 queue】,这是把递归程序改写成迭代程序的常用方法。
-
初始化时将根结点入队两次,每次提取两个结点 left 和 right 并比较它们的值(队列中每两个连续的结点应该是相等的,而且它们的子树互为镜像)
-
将两个结点的左右子结点按相反的顺序插入队列中
-
将 left.left 和 right.right 放入队列
-
将 left.right 和 right.left 放入队列
-
-
当队列为空时,或者检测到树不对称(即从队列中取出两个不相等的连续结点)时,算法结束
![image]()
class Solution:
def isSymmetric(self, root: Optional[TreeNode]) -> bool:
if not root or not (root.left or root.right): # 没有根结点或只有根结点都是对称树时直接判定对称
return True
queue = [root.left, root.right] # 队列保存结点
while queue:
# 从队列中取出两个结点,再比较这两个结点
left = queue.pop(0)
right = queue.pop(0)
# 若两个结点均为空则继续循环,若仅一个为空或均不为空格但值不相等则返回false
if not (left or right): # if not left and not right
continue
if not (left and right):
return False
if left.val != right.val:
return False
# left.left 和 right.right 入队列
queue.append(left.left)
queue.append(right.right)
# left.right 和 right.left 入队列
queue.append(left.right)
queue.append(right.left)
return True
时间复杂度:O(n),其中 n 为树的结点数量。
空间复杂度:这里需要用一个队列来维护节点,每个结点最多进队一次,出队一次,队列中最多不会超过 n 个点,故渐进空间复杂度为 O(n)。




浙公网安备 33010602011771号