【题解】对称的二叉树

对称的二叉树

题目链接:对称的二叉树

解题思路1:递归

判断一棵二叉树是不是对称,也就是判断这棵树是不是镜像,如果是镜像,那我们访问根左右和根右左的结果就是一样的,此时你可能会想先分别求出两种遍历序列,最后再对比遍历序列是否一样,就能得出结论了,但是这样相对麻烦,我们考虑使用递归,大致思路同上,不同的是我们边递归边比较,一旦有不同就直接返回,同时比较右左和左右两种,对于根左右的遍历就遍历左,此时根右左的就遍历右;对于根左右遍历右时,根右左就遍历左。

代码如下:

    bool recursion(TreeNode* root1, TreeNode* root2){
        //可以最后两个都为空
        if(root1 == nullptr && root2 == nullptr) return true;
        //如果最后只有一个为空或者对应节点值不相等,必定不对成
        if(root1==nullptr || root2==nullptr || root1->val!=root2->val)
            return false;
        //每层的对应节点进入递归
        return recursion(root1->left, root2->right) && recursion(root1->right, root2->left);
    }
    bool isSymmetrical(TreeNode* pRoot) {
        return recursion(pRoot, pRoot);
    }

解题思路2:队列+层次遍历

如果某层是镜像的,也就是是对称的,那就可以得出结论:整个该层的层次遍历的回文的,即两边互相对应相等,有节点的对应值相等,没有节点的空节点位置也对应,这样我们从左往右遍历一层和从右往左遍历一层得到的结果是一样的,注意遍历包括对空节点的遍历。我们借助队列进行层次遍历,队列是一种先进先出的数据结构,当我们遍历第一层的时候,将第一层节点的左右节点都放入队列中,队列中先左后右的放入节点,最后我们出队的时候也是先左后右的得到节点,正好对应,到遍历下一层时,我们将队列出队,出队时让该节点的子节点入队。

同时,我们不需要两个层次遍历都完整的遍历二叉树,只需要一边遍历一半即可,从左往右遍历左子树,从右往左遍历右子树,各自遍历一半互相对比即可

具体做法:

首先判空,空则直接返回对称

其次准备两个辅助队列,分别进行从左往右的遍历和从右往左的遍历,初始化第一个队列加入左节点,第二个队列加入右节点。

队列不空就进行循环,如果都为空,则有可能是空节点互相对称,我们就说这种情况暂时对称,之后从左往右加入子节点到第一个队列,从右往左加入子节点到第二个队列。

遍历结束也没有检查到不匹配,就说明是对称的

代码如下:

    bool isSymmetrical(TreeNode* pRoot) {
        if(pRoot == nullptr) return true;
        queue<TreeNode*> q1;
        queue<TreeNode*> q2;
        q1.push(pRoot->left);
        q2.push(pRoot->right);
        while(!q1.empty() && !q2.empty()){
            TreeNode* left = q1.front();
            q1.pop();
            TreeNode* right = q2.front();
            q2.pop();
            //都为空,暂时认为是对称
            if(left==nullptr && right==nullptr) continue;
            if(left==nullptr || right==nullptr || left->val!=right->val)
                return false;
            q1.push(left->left);
            q1.push(left->right);
            q2.push(right->right);
            q2.push(right->left);
        }
        return true;
    }

你可能感兴趣的:(题目练习,算法,数据结构)