描述
给定一个节点数为 n 二叉树,要求从上到下按层打印二叉树的 val 值,同一层结点从左至右输出。每一层输出一行。
例如:
给定的二叉树是{1,2,3,#,#,4,5}
返回值:[[1],[2,3],[4,5]]
方法1 非递归层序遍历
首先处理特殊情况,比如指针为空的情况,直接返回空结果[] 维护一个队列,其中存储的信息是当前层的结点指针,队列一直在第二个while循环内重复的工作就是出队当前队首结点,同时将其左右子节点入队。 在层与层之间,通过第二次while循环之前的当前队列容量大小来控制层之间的间隔。 层序遍历进行每一层的结点添加统计。
/*
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;
}
};
其中,n标志了本层结点个数,vector<> q在当前层可以起到记录下一层结点个数的功能。
复杂度分析
时间复杂度:O(N),每个节点进出队列一次
空间复杂度:O(N),使用了树状结构相当结点的空间,虽然小于N但是也是N的量级的
方法2 前序遍历记录深度
我们通过传统的前序遍历的方式,通过记录深度来判定结点对应的值应该加入到哪一个序列中。
/*
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> > res;
vector<vector<int> > Print(TreeNode* pRoot) {
PrintLevel(pRoot, 0);
return res;
}
void PrintLevel(TreeNode* pRoot,int level){
if(pRoot == NULL){
return;
}
if(res.size() < level + 1){
res.push_back({
});
}
res[level].push_back(pRoot->val);
PrintLevel(pRoot->left,level+1);
PrintLevel(pRoot->right,level+1);
}
};
其中level记录了当前递归位置的结点需要加到res的哪一层容器中。
侵删