101. Symmetric Tree*
https://leetcode.com/problems/symmetric-tree/
题目描述
Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).
For example, this binary tree [1,2,2,3,4,4,3]
is symmetric:
1
/ \
2 2
/ \ / \
3 4 4 3
But the following [1,2,2,null,3,null,3]
is not:
1
/ \
2 2
\ \
3 3
Note:
Bonus points if you could solve it both recursively and iteratively.
C++ 实现 1
先用最简单的递归方法来解决, 后面介绍迭代的方法. 对于递归的方法, 核心在于判断两个子树是否对称相等.
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
private:
bool isSymmetricSame(TreeNode *a, TreeNode *b) {
if (!a || !b) return a == b;
return (a->val == b->val) &&
isSymmetricSame(a->right, b->left) &&
isSymmetricSame(a->left, b->right);
}
public:
bool isSymmetric(TreeNode* root) {
if (!root) return true;
return isSymmetricSame(root->left, root->right);
}
};
C++ 实现 2
利用迭代的方法, 使用层序遍历; 使用两个队列, 一个队列保留左子树, 另一个队列保留右子树, 这个代码看起来比较复杂, C++ 实现 3
的逻辑更为简单, 因为她将空指针也放入到队列中了.
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if (!root) return true;
if (!root->left || !root->right) return root->left == root->right;
queue<TreeNode*> q1, q2;
q1.push(root->left);
q2.push(root->right);
while (!q1.empty() || !q2.empty()) {
auto size1 = q1.size();
auto size2 = q2.size();
// 每一层级节点个数要相等
if (size1 != size2) return false;
while (size1 --) {
auto r1 = q1.front();
q1.pop();
auto r2 = q2.front();
q2.pop();
// 同层级对应的节点值不同的情况
if (r1->val != r2->val) return false;
if (r1->left) {
if (!r2->right || r2->right->val != r1->left->val) return false;
q1.push(r1->left);
q2.push(r2->right);
} else if (r2->right) return false; // 左孩子不存在而右孩子存在的情况
if (r1->right) {
if (!r2->left || r2->left->val != r1->right->val) return false;
q1.push(r1->right);
q2.push(r2->left);
} else if (r2->left) return false;
}
}
return true;
}
};
C++ 实现 3
使用队列的方法. 注意, 空指针也是可以放入到队列中的. 根节点存入队列两次. 注意这个代码还可以进一步简化, root 无需存入队列两次; 如果存入两次, 相当于整棵树要被检查两遍. 在 C++ 实现 4
做了进一步简化.
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if (!root) return true;
if (!root->left || !root->right) return root->left == root->right;
queue<TreeNode*> q;
q.push(root);
q.push(root);
while (!q.empty()) {
auto a = q.front();
q.pop();
auto b = q.front();
q.pop();
if (!a && !b) continue;
if (!a || !b) return false;
if (a->val != b->val) return false;
q.push(a->left);
q.push(b->right);
q.push(a->right);
q.push(b->left);
}
return true;
}
};
C++ 实现 4
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if (!root) return true;
queue<TreeNode*> q;
q.push(root->left); // 直接存入左右孩子, 不管它们是不是空指针
q.push(root->right);
while (!q.empty()) {
auto a = q.front();
q.pop();
auto b = q.front();
q.pop();
if (!a && !b) continue;
if (!a || !b) return false;
if (a->val != b->val) return false;
q.push(a->left);
q.push(b->right);
q.push(a->right);
q.push(b->left);
}
return true;
}
};