代码随想Day15 | 102层序遍历、226翻转二叉树、101对称二叉树

1. 层序遍历

二叉树的层序遍历需要需要用到队列,队列先进先出,符合一层一层遍历的逻辑,而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。

详细代码如下:

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        //使用队列
        queue<TreeNode*> q;
        vector<vector<int>> res;
        if(root==nullptr) return {}; //为空直接返回
        q.push(root);  //根节点入队
        while(!q.empty())
        {
            int len = q.size(); //控制每层要输出的元素个数
            vector<int> tmp;
            for(int i=0;i<len;i++)
            {
                TreeNode* node = q.front();
                q.pop();
                tmp.push_back(node->val); //写入临时vector
                if(node->left) q.push(node->left);
                if(node->right) q.push(node->right);
            }
            res.push_back(tmp); //写入一层的元素
        }
        return res;
    }
};

当然,也可以用递归法来实现层序遍历,学了代码随想录的思路总结如下:

1. 参数:相比前序中序后序遍历,需要多一个用来表示层数的参数,来把相应的元素添加到对应层;

2. 结束条件:当节点为空就return;

3. 每层的逻辑:首先如果层数等于res的尺寸,说明开始新的一层了,需要新增一个数组;

把当前节点的val值添加到对应的res[depth]里面去;接着递归其左右节点,需要注意,其左右节点的层数要加1。

递归法的代码:

class Solution {
public:
    void layer(TreeNode* root, vector<vector<int>>&res, int depth)
    {
        if(root==nullptr) return;
        if(res.size()==depth) res.push_back(vector<int>()); //添加新层
        res[depth].push_back(root->val);
        layer(root->left,res,depth+1);
        layer(root->right,res,depth+1);  
    }
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> res;
        int depth=0;
        layer(root,res,depth);
        return res;
    }
};

层序遍历理解后,可以一下拿下10道题,只需要改上述模板的两到三行!

学会二叉树的层序遍历,可以一口气打完以下十题:

​​​

 226.翻转二叉树 

这道题的思路是前序遍历,每次处理的逻辑是交换左右节点,然后依次递归左右子树,详细代码如下:

class Solution {
public:
    void invert(TreeNode* root)
    {
        if(root==nullptr) return;
        swap(root->left,root->right);
        invert(root->left);
        invert(root->right);
    }
    TreeNode* invertTree(TreeNode* root) {
        invert(root);
        return root;
    }
};

 101. 对称二叉树 

这道题目的结束条件比较多,需要仔细思考每种情况;使用后序遍历的思路来做即可。递归三部曲:

1. 确定递归函数的参数和返回值

因为我们要比较的是根节点的两个子树是否是相互翻转的,进而判断这个树是不是对称树,所以要比较的是两个树,参数自然也是左子树节点和右子树节点。

返回值自然是bool类型。

2. 确定终止条件

要比较两个节点数值相不相同,首先要把两个节点为空的情况弄清楚!否则后面比较数值的时候就会操作空指针了。

节点为空的情况有:(注意我们比较的其实不是左孩子和右孩子,所以如下我称之为左节点右节点

  • 左节点为空,右节点不为空,不对称,return false
  • 左不为空,右为空,不对称 return false
  • 左右都为空,对称,返回true

此时已经排除掉了节点为空的情况,那么剩下的就是左右节点不为空:

  • 左右都不为空,比较节点数值,不相同就return false

此时左右节点不为空,且数值也不相同的情况我们也处理了。

3. 处理每层逻辑

对比两个外侧和内侧的左右节点是否相等,然后返回左右节点的逻辑与结果(这里体现了后序)

详细代码如下:

class Solution {
public:

    bool isEqual(TreeNode* left, TreeNode* right)
    {
        //后序遍历
        //结束条件
        if(left==nullptr&&right!=nullptr) return false;
        else if(left!=nullptr&&right==nullptr) return false;
        else if(left==right&&left==nullptr) return true;
        else if(left->val!=right->val) return false;
        bool l = isEqual(left->left,right->right);
        bool r = isEqual(left->right, right->left);
        return l&&r;

    }
    bool isSymmetric(TreeNode* root) {
        return isEqual(root->left,root->right);
        
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值