echo

任生命穿梭 时间的角落

0%

对称二叉树

101. 对称二叉树

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

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

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

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

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

进阶:

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

如果一个二叉树的左右子树镜像对称,那么这个树镜像对称。两个子树镜像对称有如下性质:

  • 左右两个子树根结点值相等

  • 每个树的右子树与另一个子树的左子树镜像对称

我们可以使用两个指针 p 和 q ,它们最开始都指向根结点,p 右移时, q 左移,p 左移时,q 右移,同时判断 p 和 q 的值是否相等并递归判断它们的子树是否镜像对称。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isSymmetric(TreeNode root) {
return check(root, root);
}

private boolean check(TreeNode p, TreeNode q){
if(p == null && q == null){
return true;
}
if(p == null || q == null){
return false;
}

return p.val == q.val && check(p.left, q.right) && check(p.right, q.left);
}
}

每个结点遍历一次,时间复杂度 O(n)。递归层数不超过 n 层,渐进空间复杂度为 O(n)。

我们还可以使用一个队列来模拟递归,每次进队列两个二叉树的镜像结点,依次判断它们的值是否相等,直到队列为空。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isSymmetric(TreeNode root) {
return check(root, root);
}

private boolean check(TreeNode u, TreeNode v){
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(u);
queue.offer(v);
while(!queue.isEmpty()){
u = queue.poll();
v = queue.poll();

if(u == null && v == null) continue;
if((u ==null || v == null) || (u.val != v.val)) return false;

queue.offer(u.left);
queue.offer(v.right);

queue.offer(u.right);
queue.offer(v.left);
}
return true;
}
}

每个结点遍历一次,时间复杂度 O(n)。每个结点入队一次,队列中最多 n 个结点,渐进空间复杂度为O(n)。