1 问题描述
判断一颗二叉树是否是“镜像对称”的。
2 代码实现
注意,这里要判断的是二叉树是不是镜像对称,因此整棵树的节点分布应该是对称的,而不是同一层的值对称,因此对称条件更加严格,需要注意不要踩坑。
2.1 迭代法实现
迭代法的思想是按层去遍历每一颗二叉树,然后判断结点是否对称,由于是镜像对称,因此还需要判断子结点的情况是否也镜像对称,在存储下一层的子结点时,可以考虑将空结点存成None
。
# 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: TreeNode) -> bool:
if root is None:
return True
else:
queue = [root]
len_q = 1 # 存下某一层节点的数目,避免重复统计
sym_signal = True
while len_q > 0:
len_q = 0
queue_now = []
for node in queue:
if node is not None:
queue_now.append(node.left)
queue_now.append(node.right)
len_q += 2
if len_q <= 0: # 表明到了最底层,不需要再循环了
break
q_start_idx = 0
q_end_idx = len_q -1 # 由于我们存储了每一个节点的左右子节点,因此某一层的节点数必为偶数
# 头尾分别遍历时,遍历到中点的下一步时,会有q_start_idx-1 = q_end_idx
while (q_start_idx-1) != q_end_idx:
if queue_now[q_start_idx] is None:
j_s = None
else:
j_s = queue_now[q_start_idx].val
if queue_now[q_end_idx] is None:
j_e = None
else:
j_e = queue_now[q_end_idx].val
if j_s == j_e:
q_start_idx += 1
q_end_idx -= 1
else:
sym_signal = False
break
if sym_signal is True:
queue = queue_now
else:
break
return sym_signal
需要遍历所有结点两次,因此时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( 2 h ) O(2^h) O(2h), h h h为树的最大高度。
2.2 递归法实现
看了官方题解才发现有个思路没想明白,就是对于一颗镜像对称的树而言,其左子树与右子树也是对称的,因此,假如也使用两个指针,一个朝左遍历,一个往右遍历,那么这两个值应该也是对应相等的。基于此就可以用递归的思想,判断树的左右子树是否是对称的,如果是,则再往上一层,以此往复即可。
# 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: TreeNode) -> bool:
if root is None:
return True
else:
return self.check(root.left, root.right)
def check(self, root1: TreeNode, root2: TreeNode) -> bool:
if root1 is None:
j1 = None
else:
j1 = root1.val
if root2 is None:
j2 = None
else:
j2 = root2.val
if j1 == j2:
if j1 is None:
return True
else:
return (self.check(root1.left, root2.right) & self.check(root1.right, root2.left))
else:
return False
return (signal & self.check(root1.left, root2.right) & self.check(root1.right, root2.left))
时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( h ) O(h) O(h), h h h为树的最大深度。