10 对称二叉树(leecode 101)

1 问题

给定一个二叉树,检查它是否是镜像对称的。
10 对称二叉树(leecode 101)

2 解法

对于二叉树是否对称,要比较的是根节点的左子树与右子树是不是相互翻转的,理解这一点就知道了「其实我们要比较的是两个树(这两个树是根节点的左右子树)」,所以在递归遍历的过程中,也是要同时遍历两棵树。

那么如果比较呢?

比较的是两个子树的里侧和外侧的元素是否相等。如图所示:
10 对称二叉树(leecode 101)

2.1 递归法

(1) 确定递归函数的参数和返回值

因为我们要比较的是根节点的两个子树是否是相互翻转的,进而判断这个树是不是对称树,所以要比较的是两个树,参数自然也是左子树节点和右子树节点。

返回值自然是bool类型。

代码如下:

bool compare(TreeNode* left, TreeNode* right)

(2) 确定终止条件

要比较两个节点数值相不相同,首先要把两个节点为空的情况弄清楚!否则后面比较数值的时候就会操作空指针了。

节点为空的情况有:

左节点为空,右节点不为空,不对称,return false
左不为空,右为空,不对称 return  false
左右都为空,对称,返回true

此时已经排除掉了节点为空的情况,那么剩下的就是左右节点不为空:

左右都不为空,比较节点数值,不相同就return false

此时左右节点不为空,且数值也不相同的情况我们也处理了。
代码如下:

if(left == nullptr && right != nullptr)    return false;
else if(left != nullptr && right == nullptr)    return false;
else if(left == nullptr && right == nullptr)    return true;
else if(left->val != right->val)   return false;

(3) 确定单层递归的逻辑
此时才进入单层递归的逻辑,单层递归的逻辑就是处理左右节点都不为空,且数值相同的情况。

比较二叉树外侧是否对称:传入的是左节点的左孩子,右节点的右孩子。
比较内侧是否对称,传入左节点的右孩子,右节点的左孩子。
如果左右都对称就返回true ,有一侧不对称就返回false 。

代码如下:

 //比较左子树的外侧与右子树的外侧
 bool outside = compare(left->left, right->right);
 //比较左子树的内侧与右子树的内侧
 bool inside = compare(left->right, right->left);
 //内侧与外侧都相等,则左右子树对称
 return outside && inside;

整体代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool compare(TreeNode* left, TreeNode* right)
    {
        if(left == nullptr && right != nullptr)    return false;
        else if(left != nullptr && right == nullptr)    return false;
        else if(left == nullptr && right == nullptr)    return true;
        else if(left->val != right->val)   return false;
        else    //left->val == right->val
        {
            //比较左子树的外侧与右子树的外侧
            bool outside = compare(left->left, right->right);
            //比较左子树的内侧与右子树的内侧
            bool inside = compare(left->right, right->left);
            //内侧与外侧都相等,则左右子树对称
            return outside && inside;
        }
    }
    bool isSymmetric(TreeNode* root) {
        if(root == nullptr)    return true;
        return compare(root->left, root->right);

    }
};

2.2 迭代法

2.2.1 使用队列

通过队列来判断根节点的左子树和右子树的内侧和外侧是否相等,如动画所示:
10 对称二叉树(leecode 101)

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
   
    bool isSymmetric(TreeNode* root) {
        if(root == nullptr)    return true;
        queue<TreeNode*> que;
        que.push(root->left);
        que.push(root->right);
        while(!que.empty())
        {
            TreeNode* leftNode = que.front();
            que.pop();
            TreeNode* rightNode = que.front();
            que.pop();
            //左右节点都为空,则对称,继续
            if(!leftNode && !rightNode)
            {
                continue;
            }
            //左右节点某个为空,另一个不为空,或左右节点的值不等
            if(!leftNode || !rightNode || leftNode->val != rightNode-> val)
                return  false;
            //左右节点值相等
            //放入左右子树的外侧节点
            que.push(leftNode->left);   
            que.push(rightNode->right);
            que.push(leftNode->right);
            que.push(rightNode->left);
        }
        return true;
    }
};
2.2.2 使用栈

这个迭代法,其实是把左右两个子树要比较的元素顺序放进一个容器,然后成对成对的取出来进行比较,那么其实使用栈也是可以的。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
   
    bool isSymmetric(TreeNode* root) {
        if(root == nullptr)    return true;
        stack<TreeNode*> st;
        st.push(root->left);
        st.push(root->right);
        while(!st.empty())
        {
            TreeNode* leftNode = st.top();
            st.pop();
            TreeNode* rightNode = st.top();
            st.pop();
            //左右节点都为空,则对称,继续
            if(!leftNode && !rightNode)
            {
                continue;
            }
            //左右节点某个为空,另一个不为空,或左右节点的值不等
            if(!leftNode || !rightNode || leftNode->val != rightNode-> val)
                return  false;
            //左右节点值相等
            //放入左右子树的外侧节点
            st.push(leftNode->left);   
            st.push(rightNode->right);
            st.push(leftNode->right);
            st.push(rightNode->left);
        }
        return true;
    }
};
上一篇:11 二叉树的最大深度(leecode 104)


下一篇:leecode:剑指offer56 数组中数字出现的次数