加载中...
101-对称二叉树(Symmetric Tree)
发表于:2021-12-03 | 分类: 简单
字数统计: 1.5k | 阅读时长: 6分钟 | 阅读量:

原文链接: https://leetcode-cn.com/problems/symmetric-tree

英文原文

Given the root of a binary tree, check whether it is a mirror of itself (i.e., symmetric around its center).

 

Example 1:

Input: root = [1,2,2,3,4,4,3]
Output: true

Example 2:

Input: root = [1,2,2,null,3,null,3]
Output: false

 

Constraints:

  • The number of nodes in the tree is in the range [1, 1000].
  • -100 <= Node.val <= 100

 

Follow up: Could you solve it both recursively and iteratively?

中文题目

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

 

例如,二叉树 [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

 

进阶:

你可以运用递归和迭代两种方法解决这个问题吗?

通过代码

高赞题解

递归实现

乍一看无从下手,但用递归其实很好解决。
根据题目的描述,镜像对称,就是左右两边相等,也就是左子树和右子树是相当的。
注意这句话,左子树和右子相等,也就是说要递归的比较左子树和右子树。
我们将根节点的左子树记做 left,右子树记做 right。比较 left 是否等于 right,不等的话直接返回就可以了。
如果相当,比较 left 的左节点和 right 的右节点,再比较 left 的右节点和 right 的左节点
比如看下面这两个子树(他们分别是根节点的左子树和右子树),能观察到这么一个规律:
左子树 $2$ 的左孩子 == 右子树 $2$ 的右孩子
左子树 $2$ 的右孩子 == 右子树 $2$ 的左孩子

    2         2
   / \       / \
  3   4     4   3
 / \ / \   / \ / \
8  7 6  5 5  6 7  8

根据上面信息可以总结出递归函数的两个条件:
终止条件:

  1. leftright 不等,或者 leftright 都为空
  2. 递归的比较 leftleftright.right,递归比较 leftrightright.left

动态图如下:
2.gif

算法的时间复杂度是 $O(n)$,因为要遍历 $n$ 个节点
空间复杂度是 $O(n)$,空间复杂度是递归的深度,也就是跟树高度有关,最坏情况下树变成一个链表结构,高度是$n$。
代码实现:

[]
class Solution { public boolean isSymmetric(TreeNode root) { if(root==null) { return true; } //调用递归函数,比较左节点,右节点 return dfs(root.left,root.right); } boolean dfs(TreeNode left, TreeNode right) { //递归的终止条件是两个节点都为空 //或者两个节点中有一个为空 //或者两个节点的值不相等 if(left==null && right==null) { return true; } if(left==null || right==null) { return false; } if(left.val!=right.val) { return false; } //再递归的比较 左节点的左孩子 和 右节点的右孩子 //以及比较 左节点的右孩子 和 右节点的左孩子 return dfs(left.left,right.right) && dfs(left.right,right.left); } }
[]
class Solution(object): def isSymmetric(self, root): """ :type root: TreeNode :rtype: bool """ if not root: return True def dfs(left,right): # 递归的终止条件是两个节点都为空 # 或者两个节点中有一个为空 # 或者两个节点的值不相等 if not (left or right): return True if not (left and right): return False if left.val!=right.val: return False return dfs(left.left,right.right) and dfs(left.right,right.left) # 用递归函数,比较左节点,右节点 return dfs(root.left,root.right)

队列实现

回想下递归的实现:
当两个子树的根节点相等时,就比较:
左子树的 left 和 右子树的 right,这个比较是用递归实现的。
现在我们改用队列来实现,思路如下:
首先从队列中拿出两个节点(leftright)比较
leftleft 节点和 rightright 节点放入队列
leftright 节点和 rightleft 节点放入队列
时间复杂度是 $O(n)$,空间复杂度是 $O(n)$
动画演示如下:
1.gif

代码实现:

[]
class Solution { public boolean isSymmetric(TreeNode root) { if(root==null || (root.left==null && root.right==null)) { return true; } //用队列保存节点 LinkedList<TreeNode> queue = new LinkedList<TreeNode>(); //将根节点的左右孩子放到队列中 queue.add(root.left); queue.add(root.right); while(queue.size()>0) { //从队列中取出两个节点,再比较这两个节点 TreeNode left = queue.removeFirst(); TreeNode right = queue.removeFirst(); //如果两个节点都为空就继续循环,两者有一个为空就返回false if(left==null && right==null) { continue; } if(left==null || right==null) { return false; } if(left.val!=right.val) { return false; } //将左节点的左孩子, 右节点的右孩子放入队列 queue.add(left.left); queue.add(right.right); //将左节点的右孩子,右节点的左孩子放入队列 queue.add(left.right); queue.add(right.left); } return true; } }
[]
class Solution(object): def isSymmetric(self, root): """ :type root: TreeNode :rtype: 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): continue if not (left and right): return False if left.val!=right.val: return False # 将左节点的左孩子, 右节点的右孩子放入队列 queue.append(left.left) queue.append(right.right) # 将左节点的右孩子,右节点的左孩子放入队列 queue.append(left.right) queue.append(right.left) return True

统计信息

通过次数 提交次数 AC比率
450323 795599 56.6%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言
上一篇:
100-相同的树(Same Tree)
下一篇:
102-二叉树的层序遍历(Binary Tree Level Order Traversal)
本文目录
本文目录