题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/symmetric-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
给定一个二叉树,检查它是否是镜像对称的。
例如,二叉树 [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
二叉树结点定义如下:
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
看到对称,我首先考虑到的是遍历然后判断回文,,后来想想这种方法不可取,首先要考虑结点 为 null 的情况,其次要是结点存在 null 那么就会判断不准确。
然后想法就是同时遍历二叉树根节点的左子树和右子树,二叉树是否是镜像对称的取决于
leftTree.left是否等于rightTree.right 且 leftTree.right 是否等于 rightTree.left
那么根据这个想法就可以得到下面的代码
public boolean isSymmetric(TreeNode root) {
//如果根节点为空,那么必然是对称
if (root == null) {
return true;
}
return isSymmetricCheck(root, root);
}
//递归
private boolean isSymmetricCheck(TreeNode p, TreeNode q) {
//如果左子树和右子树都为空,那么对称
if (p == null && q==null) {
return true;
}
//如果只有其中一边对称,那么不可能对称,返回 false
if (p == null || q == null) {
return false;
}
//递归继续判断
return p.val == q.val && isSymmetricCheck(p.left, q.right) && isSymmetricCheck(p.right, q.left);
}
下面是递归方法的执行用时、内存消耗
如果不想使用递归的形式,那么用迭代也是可以的,想法还是和前面的一样,我们只要建立一个队列,首先把根节点左右结点p、q存进去,每次都从队列中取两个结点,判断是否为 null 和结点值会否相等,然后再把取出来的结点的左右结点按顺序存进队列,由于每次都是取两个结点进行判断,那么存进去的顺序应该为 p.left -> q.right -> p.right -> q.left
具体代码如下:
public boolean isSymmetric(TreeNode root) {
//如果根节点为空,那么必然是对称
if (root == null) {
return true;
}
return isSymmetricCheck(root, root);
}
//迭代
private boolean isSymmetricCheck(TreeNode p, TreeNode q) {
Queue<TreeNode> queue = new LinkedList<TreeNode>();
//先存进左右结点(根节点)
queue.offer(p);
queue.offer(q);
while (!queue.isEmpty()) {
//每次都是取两个结点进行判断
p = queue.poll();
q = queue.poll();
//如果两个结点都是空,那么直接结束本次循环
if ( p == null && q == null) {
continue;
}
//如果只有其中一个结点为空或者两个结点对应的值不相等,
//那么此时必定不能成为镜像对称二叉树,直接返回false
if ((p == null || q == null) || (p.val != q.val)) {
return false;
}
//按照上面说的顺序存进结点
//镜像对称二叉树要 p.left.val = q.right.val
queue.offer(p.left);
queue.offer(q.right);
//同时也要满足 p.right.val = q.left.val
//所以也同时存进去,以便后面直接判断
queue.offer(p.right);
queue.offer(q.left);
}
//如果在while循环中没有返回false,
//那么证明该二叉树满足镜像对称,返回true
return true;
}
下面是迭代方法的执行时间、内存消耗
运行结果表明在该题 递归方法 无论在执行时间和内存消耗 都比迭代好一点 即使两种方法的时空复杂度都是O(n),猜测原因是,递归可以更早结束循环,所以会比迭代略快。