题目描述
给定一个二叉树,检查它是否是镜像对称的。
例如,二叉树 [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
思路
判断二叉树是否对称,下边两种方法都可以判断:
法1:
假设从根节点(root)开始判断的话,假设他的左右两个孩子为n1和n2,也就是要判断两棵以节点n1、n2为根的子树是否对称。当然,如果n1和n2都为NULL的话,肯定是对称了。如果二者中只有一个为NULL,那一定不是对称的,除开这两种情况,第三种情况就是要判断n1的left和n2的right,n1的right和n2的left,这两个条件是否都成立,如果都成立则对称,否则不对称。
法1的思路其实就是递归的一个逻辑,每个给递归函数传入两个节点,判断这两个节点的对称情况即可。
递归也可转化为迭代,迭代的话就需要用队列来做辅助,递归函数中每次传入两个节点,那么在迭代中怎么做呢?用两个队列就好了q1和q2。当然,在往这两个队列里push节点的时候,要同时push处于对称位置的两个节点,然后取出的时候正好也是取出对称位置的两个节点,才可以判断下边的子树是否对称。
法2:
使用二叉树的层序遍历,如果一个二叉树是对称的,那么它的每一层一定也是对称的,使用BFS算法逐层判断,某一层不对称了,那整棵树就不是对称的。
使用vector按顺序存储一层中所有节点的val,如果该某个位置没有节点(为NULL),就用一个特殊的标记占位(必须占位,自己想想),都加入以后,将vector逆序一下,判断逆序前后是否相等,如果相等,则这一层就是对称的。
BFS中如何判断哪些节点在同一层呢?
比如从root出发,将root节点push到队列以后,队列的size为1,处理完size(1)个节点(处理完就弹pop掉了size个节点),也就证明这一层处理完了,再加入root的两个子节点,此时队列的size为2,处理完size(2)个节点,也就把第二层处理完了。通过size变量就可以知道哪些节点在同一层了。
下面上代码
代码(递归、迭代、BFS)
递归
class Solution {
public:
bool judge(TreeNode* left, TreeNode* right){
if(left == NULL and right == NULL){
return true;
}
// 只有一个为空
if(left == NULL or right == NULL){
return false;
}
// 都不为空
return judge(left -> left, right -> right) and judge(left -> right, right -> left) and left -> val == right -> val;
}
bool isSymmetric(TreeNode* root) {
if(root == NULL){
return true;
}
// 递归法
return judge(root -> left, root -> right);
}
};
迭代
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if(root == NULL){
return true;
}
// 迭代法 递归 改迭代的话 需要用的队列来辅助
queue<TreeNode*> q1, q2;
q1.push(root -> left);
q2.push(root -> right);
while(!q1.empty() and !q2.empty()){
TreeNode* node1 = q1.front();
TreeNode* node2 = q2.front();
q1.pop();
q2.pop();
// 都空 没事; 都不空 往下判断, 只有一个是NULL就返回false
if( (node1 == NULL and node2 != NULL) or (node1 != NULL and node2 == NULL ) ){
// 只有一个是NULL
return false;
}
if(node1 != NULL and node2 != NULL){
if(node1 -> val != node2 -> val){
return false;
}else{
// val相同 往下判断 注意 q1 q2成对push,
q1.push(node1 -> left);
q2.push(node2 -> right);
q1.push(node1 -> right);
q2.push(node2 -> left);
}
}
}
return true;
}
};
BFS
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if(root == NULL){
return true;
}
// 每一层都应该是对称的,用bfs取出每一层,每一层判断一下。
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
int size = q.size();
// size用来记录一层的节点数,处理了size个就是处理好了一层的
vector<char> v; // 因为这棵树中,有的只有左节点或者右节点,缺失的节点位置就需要用一个东西来填充上,如果用数字的话,就可能和node中的val相同了,所以用char中的*来占位,vector只好定义为char型
for(int i = 0; i < size; i++){
TreeNode* node = q.front();
q.pop();
if(node == NULL){
v.push_back('*');
continue;
}
v.push_back(char('0' + node -> val));
// 把子节点加进去 等待处理
q.push(node -> left);
q.push(node -> right);
}
// 一层处理完了,判断是否对称。
vector<char> v2 = v;
reverse(v2.begin(), v2.end());
if(v != v2){
return false;
}
}
return true;
}
};