0924剑指offer

文章讲述了如何判断对称二叉树的方法,包括递归和迭代解决方案,并提到在解决类似问题时的区别,如对称与反转操作的不同。还涉及到了计算二叉树深度的递归方法。
摘要由CSDN通过智能技术生成

LCR 145. 判断对称二叉树 36min[法1看答案]+35min[法2看答案]

题目
方法一:递归
我的:没思路
原因是一直盯着“对称”二字,没有具体思考“对称”对应到逻辑上是怎样的。看了答案后才知道,其实就是一种新的树的定义,就像是二叉树的定义,满树这样的定义一样。用这个数据结构(二叉树)模拟出这个树的定义即可。
【思考】看了路飞答案后受到的思考如下,想要定义一个递归的对称二叉树。
一个树是对称二叉树,则满足:

  1. 是空树
  2. 只有一个节点,则其left==right
  3. 不止一个节点,则判断左右子树是否相等,(这里有疑惑,觉得不太对)

写的代码如下:是错的

//错误
class Solution {
public:
    bool checkSymmetricTree(TreeNode* root) {
        if(root==NULL)
            return true;
        if(root->left==NULL&&root->right==NULL) 
            return true;
        if(root->left&&root->right&&root->left->val==root->right->val)
            return true;
        else if((root->left&&root->right==NULL)||(root->left==NULL&&root->right)||(root->left&&root->right&&root->left->val!=root->right->val))
            return false;
        return checkSymmetricTree(root->left)&&checkSymmetricTree(root->right);
    }
};

【错因】:要判断的是两个树是否对称,所以每次应该传入两个数根节点,判断是否是对称的,而不是像遍历树一样,这样是判断不出来的,我写的是判断同一个树根下的左右兄弟是否值是一样的,而不没有判断整个的树。
【理清思路后写的】:

class Solution {
public:
    bool check(TreeNode* root1,TreeNode* root2)
    {
        if(root1==NULL&&root2==NULL)
           return true;
        if(root1==NULL||root2==NULL)//前面已经判断了,所以这里要么是两个不为空,要么一空一不空
           return false;
        if(root1->val!=root2->val)
           return false;
        return check(root1->left,root2->right)&&check(root1->right,root2->left);        
    }
    bool checkSymmetricTree(TreeNode* root) {
        if(root==NULL)
            return true;
        return check(root->left,root->right);
        
    }
};

方法二:迭代
用queue,但是我还是不会去判断情况
写的如下:错的,写不下去了

class Solution {
public:
    bool check(TreeNode* u,TreeNode*v)
    {
         queue<TreeNode*> q;
         q.push(u);
         q.push(v);
         while(!q.empty())
         {
             if(u->val!=v->val)
                 return false;
             if((u->left==NULL&&v->right)||(u->left&&v->right==NULL))
                 return false;
             if((u->right==NULL&&v->left)||(u->right&&v->left==NULL))
                return false;
             if(u)
         }
    }
    bool checkSymmetricTree(TreeNode* root) {
        if(root==NULL)
            return true;
        check(root,root);
        }        
    }
};

答案:

class Solution {
public:
    bool check(TreeNode* u,TreeNode*v)
    {
         queue<TreeNode*> q;
         q.push(u); q.push(v);
         while(!q.empty())
         {
            u=q.front(); q.pop();
            v=q.front(); q.pop();
            if(!u&&!v)   //都是空,则continue,这里是我不会处理的
            continue;
            if((!u||!v)||(u->val!=v->val))
               return false;
            q.push(u->left); //不用管左右子树是否为空,全部入队列,而我一直在判断,造成了复杂性
            q.push(v->right);

            q.push(u->right);
            q.push(v->left);
        }
        return true;
    }
    bool checkSymmetricTree(TreeNode* root) {
        if(root==NULL)
            return true;
        return check(root,root);       
    }
};

【反思】简化判断,空的也可以入队列,不需要检查左右子树是否为空。

LCR 144. 翻转二叉树

题目
这个题目和上面的有点相似,刚开始按照上面的思路去写,结果不对,因为反转和对称不一样,对称是轴对称,而反转是左右子树反转,小范围的,镜像是大范围轴对称的,因此这个的递归不需要传入两个参数,只需要dfs遍历即可。
错的:

class Solution {
public:
    void reverseTree(TreeNode* u,TreeNode*v)
    {
        if(!u&&!v)
           swap(u->val,v->val);
        if(u->left&&v->right) reverseTree(u->left,v->right);
        if(u->right&&v->left) reverseTree(u->right,v->left);
    }

    TreeNode* mirrorTree(TreeNode* root) {
        if(root==NULL) return NULL;
        reverseTree(root->left,root->right);
        return root;
    }
};

正确的:

class Solution {
public:
    TreeNode* mirrorTree(TreeNode* root) {
        if(root==NULL) return NULL;
        TreeNode* t=root->left;
        root->left=mirrorTree(root->right);
        root->right=mirrorTree(t);
        return root;
    }
};

LCR 175. 计算二叉树的深度

题目
计算二叉树的高度

class Solution {
public:
    int calculateDepth(TreeNode* root) {
        if(root==NULL) return 0;
        if(root->left==NULL&&root->right==NULL)  return 1;
        int lh=calculateDepth(root->left);
        int rh=calculateDepth(root->right);
        if(lh>rh) return lh+1;
        return rh+1;

    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值