Title

给定一个二叉树,检查它是否是镜像对称的。

例如,二叉树 [1,2,2,3,4,4,3] 是对称的。

    1
   / \
  2   2
 / \ / \
3  4 4  3

但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:

    1
   / \
  2   2
   \   \
   3    3

Solve

递归:深度优先

如果一个树的左子树与右子树镜像对称,那么这个树是对称的。

101. Symmetric Tree_复杂度分析
所以此问题可以转化为:两棵树在什么情况下互为镜像?必须满足以下条件:

  1. 它们的两个根节点具有相同的值
  2. 每个树的右子树与另一个树的左子树镜像对称

101. Symmetric Tree_子树_02
可以实现一个递归函数,通过「同步移动」两个指针的方法来遍历这棵树,p 指针和 q 指针一开始都指向这棵树的根,随后 p 右移时,q 左移,p 左移时,q 右移。每次检查当前 p 和 q 节点的值是否相等,如果相等再判断左右子树是否对称。

	def isSymmetric_D(self, root: TreeNode) -> bool:
		def check(p: TreeNode, q: TreeNode):
			if p is None and q is None:
				return True
			if p is None or q is None:
				return False
			return p.val == q.val and check(p.left, q.right) and check(p.right, q.left)

		return check(root, root)

复杂度分析

假设树上一共 n 个节点。

时间复杂度:这里遍历了这棵树,渐进时间复杂度为 O(n)。

空间复杂度:这里的空间复杂度和递归使用的栈空间有关,这里递归层数不超过 n,故渐进空间复杂度为 O(n)。

迭代:广度优先

引入一个队列,初始化时把根节点入队两次,每次提取两个节点并比较它们的值,队列中每两个连续的节点英爱是相等的,而且它们的子树互为镜像,然后将两个节点的左右子节点按相反的顺序插入队列中,当队列为空时,或者我们检测到树不对称时,算法结束。

	def isSymmetric_B(self, root: TreeNode) -> bool:
		def check(x: TreeNode, y: TreeNode):
			from queue import Queue
			q = Queue()
			q.put(x)
			q.put(y)
			while not q.empty():
				u = q.get()
				v = q.get()
				if not u and not v:
					continue
				if (not u or not v) or (u.val != v.val):
					return False
				q.put(u.left)
				q.put(v.right)
				q.put(u.right)
				q.put(v.left)
			return True

		return check(root, root)

复杂度分析

时间复杂度:O(n),这里遍历了这棵树,渐进时间复杂度为 O(n)。

空间复杂度:这里需要用一个队列来维护节点,每个节点最多进队一次,出队一次,队列中最多不会超过 n 个点,故渐进空间复杂度为 O(n)。