代码随想录算法训练营day15

本文介绍了二叉树的层序遍历算法,包括BFS实现以及存储每一层元素的方法。同时探讨了翻转二叉树的递归和迭代解决方案,以及对称二叉树的判断策略,强调了递归、比较方法和边界条件的重要性。
摘要由CSDN通过智能技术生成

题目:层序遍历、226.翻转二叉树、101. 对称二叉树

参考链接:代码随想录

层序遍历

102.二叉树的层序遍历
107.二叉树的层次遍历II
199.二叉树的右视图
637.二叉树的层平均值
429.N叉树的层序遍历
515.在每个树行中找最大值
116.填充每个节点的下一个右侧节点指针
117.填充每个节点的下一个右侧节点指针II
104.二叉树的最大深度
111.二叉树的最小深度

思路:层序遍历就是BFS,即一层一层遍历。需要使用一个queue,首先将根节点入队,如果队列不为空,则出队。如果队头存在孩子,则将其左右孩子入队,依次类推。
但我在代码实现的时候虽然能够完成遍历,但没想到如何将每一层的所有元素放到一个vector中,看标答后才发现需要记录队列长度即可,即为每一层的长度。时间复杂度O(n),遍历都是O(n)。

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode*> q;
        vector<vector<int>> ans;
        if(root){
            q.push(root);
        }
        while(!q.empty()){
            int size=q.size();
            vector<int> tmp={};
            for(int i=0;i<size;i++){
                if(q.front()->left){
                    q.push(q.front()->left);
                }
                if(q.front()->right){
                    q.push(q.front()->right);
                }
                tmp.push_back(q.front()->val);
                q.pop();
            }
            ans.push_back(tmp);
        }
        return ans;
    }
};

递归算法没细看,感觉不是很实用,空间复杂度也高,对BFS主要是掌握队列使用。
其他剩余题目都不难,思路都类似。
每行找最大值那题可以直接定义max=INT_MIN,在每层遍历的时候就比较,不需要再单独定义一个函数。
最小深度不需要全部遍历完,找到第一个叶子节点的深度必定最小,可以直接返回。

226.翻转二叉树

思路:递归思想,先考虑根节点,递归返回条件即为根节点为空,或者其左右孩子都为空,然后正常递归即可。时间复杂度O(n)。

class Solution {
public:
    void invTree(TreeNode* root){
        if(!root||(!root->left&&!root->right)){//自己为空或者左右节点都为空则不需要操作
            return;
        }
        else{
            swap(root->left,root->right);
            invTree(root->left);
            invTree(root->right);
        }
        
    }
    TreeNode* invertTree(TreeNode* root) {
        invTree(root);
        return root;
    }
};

看完标答发现前序后序遍历都可以,我进行的是前序遍历,所以可以不加左右节点都不为空的那个判断。然后还可以使用迭代法写。

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        stack<TreeNode*> st;
        if(!root){
            return nullptr;
        }
        st.push(root);
        while(!st.empty()){
            TreeNode* node=st.top();
            st.pop();
            swap(node->left,node->right);
            if(node->right) st.push(node->right);
            if(node->left) st.push(node->left);
        }
        return root;
    }
};

101. 对称二叉树

思路:本题想了很久没找到思路,主要不知道如何遍历能比较两个子树是否对称。看了解析需要将对比两边子树单独写成一个函数,比较子树对称的时候,需要比较其外侧子树是否对称,还有其内侧子树是否对称。对于结束条件,要想清楚空指针的情况,如果要比较的两个节点两个为空则对称,一个为空一个不为空则不对称,两个都不为空则正常比较。

class Solution {
public:
    bool compare(TreeNode* l,TreeNode* r){
        if(!l&&!r){
            return true;
        }
        else if(!l||!r){
            return false;
        }
        else{//都不为空
            if(l->val!=r->val){//如果值都不等直接false
                return false;
            }
            return compare(l->left,r->right)&&compare(l->right,r->left);
        }
    }
    bool isSymmetric(TreeNode* root) {
        if(!root){
            return true;
        }
        return compare(root->left,root->right);
    }
};

个人感觉解析中说的后序遍历不是很对,本题就是一个对外侧节点和内侧节点的分别比较,并不存在什么遍历。
使用迭代写法,队列和栈可以,主要用于比较容器前面两个元素是否相等。

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if(!root){
            return true;
        }
        queue<TreeNode*> q;
        q.push(root->left);
        q.push(root->right);
        while(!q.empty()){
            TreeNode* leftNode=q.front();
            q.pop();
            TreeNode* rightNode=q.front();
            q.pop();
            if(!leftNode&&!rightNode){//都为空说明对称
                continue;
            }
            if(!leftNode||!rightNode||leftNode->val!=rightNode->val){
                return false;//不等直接false
            }
            q.push(leftNode->left);
            q.push(rightNode->right);
            q.push(leftNode->right);
            q.push(rightNode->left);
        }
        return true;
    }
};
  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值