101. 对称二叉树

本文介绍了判断对称二叉树的三种方法。首先尝试用二叉树中序遍历判断,发现不可行;接着介绍递归法,在dfs中传入两个节点指针;然后是迭代法,用pair变量存储节点并压入队列判断;最后提到传统方法,按对称定义,先拷贝树的镜像再对比。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

采用递归和迭代两种方法:

(1)递归:

在一开始做的时候,试图用二叉树的中序遍历来做。因为我发现对于对称的二叉树,中序遍历的结果也是对称的。所以以为,构建一个vector,然后中序遍历一遍,然后对这个vector,看是否对称,即可得到是否是对称二叉树。但是,运行时一个反例,让我明白这个简单粗暴的方法是不行的。比如下面这个例子,【1,2,3,3,null,2,null】这棵非对称二叉树的中序遍历结果为3,2,1,2,3

看似是对称的,但是其实这不是一棵对称的树。

所以,该方法不行。

https://leetcode-cn.com/problems/symmetric-tree/description/   可以考虑采用上述的做法,即dfs中传入两个节点指针,分别往两个方向走。这样的递归非常的灵活,感觉又收获了新技能。

注意,leetcode第100题也是采用了传入了双指针,但是100题比较明显是要传入双指针,因为那是两棵树。

(2)迭代:这种方法从形式上类似我们递归的思路,即也是排查一个节点的左子树和另一个节点的右子树,以及一个节点的右子树和另一个节点的左子树,使用一个pair的变量存储,并压入到队列里。然后在弹出时进行结构(判空)和值(判值)的判断。这题AC的代码是我自己写的,但是思路是借鉴的b站视频的,他是用100题讲得迭代方法。可以回头再看一遍。

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(root==NULL) return true;
        queue<pair<TreeNode*,TreeNode*> > q;
        q.push(make_pair(root,root));
        while(!q.empty())
        {
            pair<TreeNode*,TreeNode*> temp=q.front();
            q.pop();
            // if(temp.first==temp.second&&temp.first!=NULL)  
            if((temp.first==NULL&&temp.second!=NULL)||(temp.first!=NULL&&temp.second==NULL))
            {
                return false;
            }
            
            if(temp.first!=NULL&&temp.second!=NULL)
            {
                
            if(temp.first->val!=temp.second->val)
            {
                return false;
            }
            
            
            if(temp.first->left!=NULL&&temp.second->right!=NULL)
            {
                q.push(make_pair(temp.first->left,temp.second->right));
            }else if(temp.first->left==NULL&&temp.second->right==NULL)
            {
                q.push(make_pair(temp.first->left,temp.second->right));
            }else return false;
            
            
            if(temp.first->right!=NULL&&temp.second->left!=NULL)
            {
                q.push(make_pair(temp.first->right,temp.second->left));
            }else if(temp.first->right==NULL&&temp.second->left==NULL)
            {
                q.push(make_pair(temp.first->right,temp.second->left));
            }else return false;
            
            }
        }
        
        return true;
        
    }
};

 

 

(3)还有一种比较传统的方法,即按照对称的原始定义:如果一棵树的镜像和它是同样的,则称为是对称的。

注意,这样做的时候,需要提前拷贝出一个树的镜像,否则会破坏原来树的结构。

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/

///如果用题目给出的做法,则先拷贝一份,然后利用拷贝的那份再去输出镜像
class Solution {
public:
    TreeNode* copyRoot(TreeNode* pRoot)
    {
        if(pRoot==NULL) return NULL;
        TreeNode* root=new TreeNode(pRoot->val);
        root->left=copyRoot(pRoot->left);
        root->right=copyRoot(pRoot->right);
        return root;
    }
    
    void jingxiang(TreeNode* root)
    {
        if(root==NULL) return;
        jingxiang(root->left);
        jingxiang(root->right);
        swap(root->left,root->right);
    }
    
    bool dfs(TreeNode* p1,TreeNode* p2)
    {
        if(p1==NULL&&p2==NULL) return true;
        if( (p1!=NULL&&p2!=NULL) && (p1->val==p2->val))  //这里的非空判断一定要有,因为只有保持非空,才能用下面的左右子树
        {
        return dfs(p1->left,p2->left) && dfs(p1->right,p2->right);
        }
        else return false;
    }
    
    bool isSymmetrical(TreeNode* pRoot)
    {
       TreeNode* cRoot=copyRoot(pRoot);
       jingxiang(cRoot);
       return dfs(pRoot,cRoot);
    }

};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值