对称二叉树 1.题目内容 给你一个二叉树的根节点 root , 检查它是否轴对称。
示例 1:
1 2 输入:root = [1,2,2,3,4,4,3] 输出:true
示例 2:
1 2 输入:root = [1,2,2,null,3,null,3] 输出:false
提示:
树中节点数目在范围 [1, 1000] 内
-100 <= Node.val <= 100
2.解法 (1)递归 思路及算法
如果一个树的左子树与右子树镜像对称,那么这个树是对称的。
因此,该问题可以转化为:两个树在什么情况下互为镜像?
如果同时满足下面的条件,两个树互为镜像:
它们的两个根结点具有相同的值
每个树的右子树都与另一个树的左子树镜像对称
我们可以实现这样一个递归函数,通过「同步移动」两个指针的方法来遍历这棵树,p 指针和 q 指针一开始都指向这棵树的根,随后 p 右移时,q 左移,p 左移时,q 右移。每次检查当前 p 和 q 节点的值是否相等,如果相等再判断左右子树是否对称。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 //Java class Solution { public boolean isSymmetric(TreeNode root) { return check(root, root); } public 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); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 //C++ class Solution { public: bool check(TreeNode *p, TreeNode *q) { if (!p && !q) return true; if (!p || !q) return false; return p->val == q->val && check(p->left, q->right) && check(p->right, q->left); } bool isSymmetric(TreeNode* root) { return check(root, root); } };
复杂度分析
假设树上一共 n 个节点。
时间复杂度:这里遍历了这棵树,渐进时间复杂度为 O(n)。
空间复杂度:这里的空间复杂度和递归使用的栈空间有关,这里递归层数不超过 n,故渐进空间复杂度为 O(n)。
(2)迭代 思路及算法
首先我们引入一个队列,这是把递归程序改写成迭代程序的常用方法。初始化时我们把根节点入队两次。每次提取两个结点并比较它们的值(队列中每两个连续的结点应该是相等的,而且它们的子树互为镜像),然后将两个结点的左右子结点按相反的顺序插入队列中。当队列为空时,或者我们检测到树不对称(即从队列中取出两个不相等的连续结点)时,该算法结束。
代码
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 //Java class Solution { public boolean isSymmetric(TreeNode root) { return check(root, root); } public boolean check(TreeNode u, TreeNode v) { Queue<TreeNode> q = new LinkedList<TreeNode>(); q.offer(u); q.offer(v); while (!q.isEmpty()) { u = q.poll(); v = q.poll(); if (u == null && v == null) { continue; } if ((u == null || v == null) || (u.val != v.val)) { return false; } q.offer(u.left); q.offer(v.right); q.offer(u.right); q.offer(v.left); } return true; } }
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 //C++ class Solution { public: bool check(TreeNode *u, TreeNode *v) { queue <TreeNode*> q; q.push(u); q.push(v); while (!q.empty()) { u = q.front(); q.pop(); v = q.front(); q.pop(); if (!u && !v) continue; if ((!u || !v) || (u->val != v->val)) return false; q.push(u->left); q.push(v->right); q.push(u->right); q.push(v->left); } return true; } bool isSymmetric(TreeNode* root) { return check(root, root); } };
复杂度分析
时间复杂度:O(n)。
空间复杂度:这里需要用一个队列来维护节点,每个节点最多进队一次,出队一次,队列中最多不会超过 n 个点,故渐进空间复杂度为 O(n)。