LeetCode 102. 二叉树的层序遍历的两种解法

题目概述:

在这里插入图片描述

解法:

一、利用广度优先遍历

  非常显然,如果把树看成一种简化的图,前序遍历就是一种广度优先遍历,那么自然可以按照广度优先遍历的思想实现前序遍历,具体来说,我们需要一个队列q,先检查root是否为空,不为空则让root入队,并且为返回的二维数组容器vec扩容,根据我们后面的设计,会发现q的大小正是二叉树的这一层结点的个数,所以用 c u r r e n t L e v e l S i z e = q . s i z e ( ) ; currentLevelSize = q.size(); currentLevelSize=q.size();得到当前层数的节点个数,然后利用一个for循环,从q取队头,pop,把队头对应的值插入到vec.back()的后一个位置,检查队头节点的左孩子不为空则入队列,检查队头结点的右孩子不为空则入队列,这里用back()方法就会得到数组的最后一个元素,也就是对应储存当前层的结点的 v e c t o r < i n t > vector<int> vector<int>,这样进行 c u r r e n t L e v e l S i z e currentLevelSize currentLevelSize次,直到队列为空时结束.
  从这里也可以看出,每次都会在for循环中把下一层的结点加入队尾,上一层的结点pop()出队列,所以每次for循环结束,队列的长度正是下一层的结点个数,并且一开始的时候,我们让root入队列,也正好对应了第一层的结点个数是1,不得不说是很巧妙的。
代码:

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

时间复杂度: O ( n ) O(n) O(n),n是结点个数
空间复杂度: O ( l ) O(l) O(l),l是二叉树中一层中结点个数的最大值

二、利用前序遍历实现层序遍历

  这个思想真的很巧妙,我们都知道前序遍历会先访问自己,再访问自己的左孩子,再访问自己的右孩子,我们只要在前序遍历的函数参数中加一个 d e p t h depth depth控制当前结点对应的深度(这里从0开始记深度)就可以了,进入前序遍历函数后,先检查当前结点是否为空,如果不为空,再检查当前深度 d e p t h depth depth是否大于等于 v e c t o r < v e c t o r < i n t > > a n s vector<vector<int>> ans vector<vector<int>>ans的大小(或者改为 d e p t h + 1 depth + 1 depth+1是否大于当前容器大小,这样更直观),如果是,那么说明当前层还没有来过,需要扩容;以上行动结束后,我们把当前结点的值插入到 a n s [ d e p t h ] ans[depth] ans[depth]的最后一个元素,然后去遍历当前结点的左子树和右子树,只不过需要参数 d e p t h depth depth设置为 d e p t h + 1 depth + 1 depth+1
代码:

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) 
    {
        vector<vector<int>> vec;
        if (root == nullptr)
        {
            return vec;
        }
        preTraverse(root, 0, vec);
        return vec;
    }
    void preTraverse(TreeNode* root, int depth, 
    vector<vector<int>>& ans)
    {
        if (root == nullptr)
        {
            return;
        }
        if (depth >= ans.size())
        {
            //如果深度大于数组的长度 说明这一层还没来过 需要扩容
            ans.push_back(vector<int> {});
        }
        ans[depth].push_back(root->val);
        preTraverse(root->left, depth + 1, ans);
        preTraverse(root->right, depth + 1, ans);

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值