思路

题目要求我们将同一层按照从左到右的顺序进行合并整理成输出,我们将题目解读并翻译为层序遍历问题

  • 通过层序遍历的方式进行顺序访问
  • 维护一个队列结构,队列可以帮助我们实现先进先出,因此只要层序访问入队出队即可

方法一:非递归层序遍历

具体做法 首先处理特殊情况,比如指针为空的情况,直接返回空结果[] 维护一个队列,其中存储的信息是当前层的结点指针,队列一直在第二个while循环内重复的工作就是出队当前队首结点,同时将其左右子节点入队。 在层与层之间,通过第二次while循环之前的当前队列容量大小来控制层之间的间隔。 层序遍历进行每一层的结点添加统计 图片说明

以下为c++代码展示

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
        vector<vector<int> > Print(TreeNode* pRoot) {
            if(pRoot==NULL) return {};                // 指针为空的情况处理
            vector<vector<int>> res;
            queue<TreeNode*> q;                       // 采用队列非递归的方式进行层序遍历
            TreeNode* p = pRoot;
            q.push(p);                                // 首先将根节点入队
            while(!q.empty()) {                       // 判断当前层是否为空
                vector<int> level;
                int n = q.size();                     // 获取当前层内的结点数量
                while(n){                             // 对当前层内每一个结点进行左右子树的访问
                    TreeNode* a = q.front();          // 队首按序出列即当前层的vector内容
                    if(a->left) q.push(a->left);      // 左孩子入队
                    if(a->right)q.push(a->right);     // 右孩子入队
                    q.pop();                          // 当前层的结点指针出队
                    level.push_back(a->val);          // 将当前层结点记录到本层的vector中
                    n--;
                }
                res.push_back(level);                 // 收集每一层的vector整合为最终结果
            }
            return res;
        }
    
};

复杂度分析

  • 时间复杂度:O(N),每个节点进出队列一次
  • 空间复杂度:O(N),使用了树状结构相当结点的空间,虽然小于N但是也是N的量级的

方法二:前序遍历记录深度

我们通过传统的前序遍历的方式,通过记录深度来判定结点对应的值应该加入到哪一个序列中

class Solution {
public:
        vector<vector<int>> res;
        void preOrder(TreeNode* root,int deep) {
            if(!root) return;                            // 如果当前结点为空则直接返回
            if(deep > res.size()) res.push_back({});     // 达到一个深度级就会在res中增加一个空序列
            res[deep-1].push_back(root->val);            // 在res中对应深度的序列中添加元素
            preOrder(root->left,deep+1);                 // 递归左子树,并深度+1
            preOrder(root->right, deep+1);               // 递归右子树,并深度+1
        }
        vector<vector<int> > Print(TreeNode* pRoot) {
            preOrder(pRoot,1);                           // 前序遍历,保证同一层内的访问顺序是从左到右的
            return res;
        }
};

复杂度分析

  • 时间复杂度:O(N),每个节点进出队列一次
  • 空间复杂度:O(N),维护递归的栈空间