day-15 代码随想录算法训练营(19) 二叉树part02(层序遍历、递归)已二刷

226.翻转二叉树

思路一:使用队列层序遍历
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        //思路:层序遍历,判断每一个节点是否有左右节点,分三种情况
        queue<TreeNode*>que;
        if(root==nullptr)
            return root;
        que.push(root);//加入根节点
        while(!que.empty())
        {
            int len=que.size();
            cout<<len;
            for(int i=0;i<len;i++)//遍历队列内节点
            {
                TreeNode*cur=que.front();
                //cout<<cur->val<<"\t";
                
                if(cur->left!=nullptr  && cur->right!=nullptr)//分三种情况讨论
                {
                    TreeNode*temp=cur->left;
                    cur->left=cur->right;
                    cur->right=temp;
                    que.push(cur->left);
                    que.push(cur->right);
                }
                else if(cur->left!=nullptr && cur->right==nullptr)
                {
                    cur->right=cur->left;
                    cur->left=nullptr;
                    que.push(cur->right);
                }
                else if(cur->right!=nullptr && cur->left==nullptr)
                {
                    cur->left=cur->right;
                    cur->right=nullptr;
                    que.push(cur->left);
                }
                // else 
                //     cout<<1<<endl;
                que.pop();
            }
        }
        return root;
    }
};

问题:刚开始没判断root是否为为空,调试打印数据看着很乱,还以为哪出问题了

总结:极端条件一开始就需要考虑!!!

思路二:递归,直接使用swap函数交换左右节点在父节点那的位置
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        //思路:层序遍历,判断每一个节点是否有左右节点,分三种情况
        if(root==nullptr)
            return root;
        swap(root->left,root->right);
        invertTree(root->left);
        invertTree(root->right);
        return root;
    }
};
二刷:
思路:两两节点交换+递归遍历
class Solution {
public:
    void swapNode(TreeNode*root,TreeNode*left,TreeNode*right){
        if(left && right){
            root->right=left;
            root->left=right;
        }
        else if(left){
            root->right=left;
            root->left=nullptr;
        }
        else if(right) {
            root->left=right;
            root->right=nullptr;
        }
    }
    TreeNode* invertTree(TreeNode* root) {
       if(root==nullptr) return root;
       swapNode(root,root->left,root->right);
       invertTree(root->left);
       invertTree(root->right);
       return root;
    }
};

101.对称二叉树

思路一:没想到还能这么遍历,直接比较两颗二叉树
class Solution {
public:
    bool compare(TreeNode*left,TreeNode*right)
    {
        //首先排除节点为空的情况
        if(left==nullptr && right==nullptr) return true;
        else if(left!=nullptr && right==nullptr) return false;
        else if(left==nullptr && right!=nullptr) return false;
        //下面左右节点都存在
        else if(left->val!=right->val) return false;

        //此时左右节点都不为空,且数值相同
        bool outside=compare(left->left,right->right);
        bool inside=compare(left->right,right->left);
        bool isSame=outside && inside;
        return isSame;
    }
    bool isSymmetric(TreeNode* root) {
        //思路:
        if(root==nullptr) return true;
        return compare(root->left,root->right);
    }
};
思路二:先翻转左二叉树,然后跟右二叉树作比较

越搞越复杂,放弃

 二刷:
思路一:直接把根节点的两个子节点放入,后面分开遍历判断
class Solution {
public:
    bool judge(TreeNode*left,TreeNode*right){
        
        if(left==nullptr && right==nullptr) return true;//都为空
        if(left==nullptr || right==nullptr) return false;//有一个为空
        if(left->val!=right->val) return false;//不相等
        
        bool judge1=judge(left->left,right->right);//外层情况
        bool judge2=judge(left->right,right->left);//内层情况
        return judge1 && judge2;
    }
    bool isSymmetric(TreeNode* root) {
        return judge(root->left,root->right);
    }
};

114.二叉树展开为链表

思路一:先前序遍历存入数组,在依次改变节点的连接
class Solution {
public:
    void judge(TreeNode*root,vector<TreeNode*>&nodes)
    {
        if(root==nullptr)
            return;
        nodes.push_back(root);
        judge(root->left,nodes);
        judge(root->right,nodes);
    }
    void flatten(TreeNode* root) {
        //思路一:先序遍历,节点加入容器,然后连接
        //思路二:递归直接改变指针
        vector<TreeNode*>nodes;
        if(root==nullptr)
            return;
        judge(root,nodes);
        //cout<<nodes.size();
        if(nodes.size()==1)
            return;
        TreeNode*head=new TreeNode();
        TreeNode*pre=head;
        for(auto node:nodes)
        {
            pre->right=node;
            node->left=nullptr;
            pre=node;
        }
    }
};
 二刷路过:
class Solution {
public:
    vector<TreeNode*>nodes;
    void judge(TreeNode*cur){
        if(cur==nullptr) return;
        nodes.push_back(cur);
        judge(cur->left);
        judge(cur->right);
    }
    void flatten(TreeNode* root) {
        judge(root);
        int n=nodes.size();
        for(int i=0;i<n-1;i++){
            nodes[i]->left=nullptr;
            nodes[i]->right=nodes[i+1];
        }
    }
};

 

104.二叉树的最大深度

思路:层序遍历
class Solution {
public:
    int maxDepth(TreeNode* root) {
        //层序遍历
        if(root==nullptr)
            return 0;
        queue<TreeNode*>que;
        que.push(root);
        int deep=0;
        while(!que.empty())
        {
            int len=que.size();
            for(int i=0;i<len;i++)
            {
                TreeNode*cur=que.front();
                que.front();
                que.pop();
                if(cur->left)
                    que.push(cur->left);
                if(cur->right)
                    que.push(cur->right);
            }
            deep++;
        }
        return deep;

    }
};

 

二刷:
思路:深度比较,前序遍历
class Solution {
public:
    void judge(TreeNode*root,int deep,int&maxdeep){
        if(root==nullptr) return;
        if(deep>maxdeep) maxdeep=deep;
        judge(root->left,deep+1,maxdeep);
        judge(root->right,deep+1,maxdeep);
    }
    int maxDepth(TreeNode* root) {
       int maxdeep=0;
       judge(root,1,maxdeep);
       return maxdeep;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值