【剑指Offer】面试题59:对称二叉树

整理自剑指Offer

一:题目描述


请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。


二:解题思路


看到这个题第一反应是求二叉树的镜像二叉树,然后同时遍历两个树,进行比较

遇到问题 :在求二叉树的镜像二叉树改变了原始的二叉树的结构,不可行


剑指Offer的解法:

如上图,我们可以看出第一个二叉树是对称的,第二棵与第三棵是不对称的


对树的遍历有三种方式:前序遍历,中序遍历,后序遍历,在这三种方法中都是先遍历左子结点再遍历右子节点。

是否可以定义一种新的遍历方式,先遍历右子节点再遍历左子结点


如先序遍历:父结点,左子结点,右子节点

定义的基于先序遍历的新的遍历方式:父结点,右子节点,左子结点

如果两者输出的结果相同,则说明这个二叉树是对称的


如上图第一棵树:

先序遍历 8、6、5、7、6、7、5

新的遍历8、6、5、7、6、7、5

对称

第二棵树:

先序遍历:8、6、5、7、9、7、5

新的遍历:8、9、5、7、6、7、5

不对称

第三棵树

先序遍历:7、7、7、7、7、7

新的遍历:7、7、7、7、7、7

对称?不对


如何解决这个问题:将叶子节点的NULL加入其中就可以解决


第三棵树:

先序遍历:7、7、7、NULL、NULL、7、NULL、NULL、7、7、NULL、NULL、NULL

新的遍历:7、7、NULL、7、NULL、NULL、7、NULL、NULL、7、NULL、NULL

不对称



三:代码实现

递归版代码

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    
    bool isSymmetricalCore(TreeNode* pRoot1,TreeNode* pRoot2){
        
        if(pRoot1==NULL && pRoot2==NULL)
            return true;
        if(pRoot1==NULL || pRoot2==NULL)
            return false;
        if(pRoot1->val!=pRoot2->val)
            return false;
        //阶梯思想容易理解,但是递归的代码不易理解
        //可以将pRoot1看成是先序遍历的指针,先左后右
        //可以将pRoot2看成是新的遍历的指针,先右后左
        //如果两者相同,比较下一个对称位置的结点
        //如果不相等,返回false
        return isSymmetricalCore(pRoot1->left,pRoot2->right)&&
            isSymmetricalCore(pRoot1->right,pRoot2->left);
    }
    
    bool isSymmetrical(TreeNode* pRoot)
    {
        //递归版本
    
        //根节点为空指针,认为是对称的
        if(pRoot==NULL)
            return true;
 		return isSymmetricalCore(pRoot,pRoot);
   }

};

非递归版代码--队列方式实现

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    bool isSymmetrical(TreeNode* pRoot)
    {
      
        if(pRoot==NULL)
            return true;
        //利用两个队列保存两种遍历的结果,队列先进先出
        //q1:先序遍历结果  q2:新的遍历的结果
        queue<TreeNode*>q1,q2;
        TreeNode *left,*right;
        //入队
        q1.push(pRoot->left); //先左后右
        q2.push(pRoot->right); //先右后左
        while(!q1.empty() && !q2.empty()){
            
            left=q1.front();  //取队首元素
            q1.pop();   //出队
            right=q2.front();
            q2.pop();
            
            //对称位置均空,继续
            if(left==NULL && right==NULL)
                continue;
            //对称位置一空一不空,不对称
            if(left==NULL || right==NULL)
                return false;
            //对称位置值不相同,不对称
            if(left->val!=right->val)
                return false;
            
            q1.push(left->left);
            q1.push(left->right);
            q2.push(right->right);
            q2.push(right->left);
            
        }
        return true;
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值