一、题目描述
从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
例如:
给定二叉树[3,9,20,null,null,15,7]
3
/ \
9 20
/ \
15 7
返回:
[
[3],
[9,20],
[15,7]
]
提示:
节点总数<=1000
二、思路分析
注:思路分析中的一些内容和图片参考自力扣各位前辈的题解,感谢他们的无私奉献
思路
①按层打印:题目要求的二叉树的层序遍历又称为二叉树的广度优先搜索(BFS)。BFS通常借助队列的先入先出特性来实现。
②每层打印到一行:将本层全部结点打印到一行,并将下一层全部结点加入队列,以此类推,即可分为多行打印。
算法流程:
1、特例处理:当根结点为空,则返回空列表[]
;
2、初始化:定义用于返回的二维数组res
,定义队列queue
,将根结点入队
3、BFS循环:当队列queue
为空时跳出;
----3.1 计算出队列的长度,也就是当前层的结点数。
----3.2 当前层打印循环,循环次数为当前层结点数
------3.2.1 出队:队首元素出队,记为tmp
------3.2.2 打印:将tmp.val
添加至res
对应的地方
------3.2.3 添加子节点:若tmp
的左(右)子结点不为空,则将左(右)子结点加入队列queue
4、返回值:返回二维数组res
即可。
复杂度分析:
时间复杂度 O ( N ) \rm{O(N)} O(N):N
为二叉树的结点数量,即BFS需循环N
次。
空间复杂度 O ( N ) \rm{O(N)} O(N): 最差情况下,即当树为平衡二叉树时,最多有N/2
个树结点同时在queue
中,使用O(N)
大小的额外空间。
三、整体代码
整体代码如下
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
/**
* Return an array of arrays of size *returnSize.
* The sizes of the arrays are returned as *returnColumnSizes array.
* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
*/
int** levelOrder(struct TreeNode* root, int* returnSize, int** returnColumnSizes) {
//树为空时
if (!root) {
*returnSize = 0;
*returnColumnSizes = NULL;
return NULL;
}
*returnSize = 0; //返回数组的行数,即二叉树的高度
int** res = (int**)malloc(sizeof(int*) * 10001); //返回数组
*returnColumnSizes = (int*)malloc(sizeof(int) * 10001); //返回数组中每一行的列数
struct TreeNode** queue = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 10001); //新建队列
int head = -1; //head为队首下标,初始化为-1,代表没有元素
int rear = 0; //rear为队尾元素后面的位置,初始化为0,代表需要入的元素插入到这个地方
queue[++head] = root; //将根结点插入,队首坐标往后挪
rear++; //队尾位置往后挪
//遍历二叉树
while (head < rear) {
/*
记录当前的rear,因为我们要对树的每一层进行遍历,每一层的结点数=rear-head
而在遍历每一层过程中,要对各个结点左右孩子进行入队,此时rear又要变化
所以定义一个preRear,根据这个preRear控制对当前层的遍历
*/
int preRear = rear;
res[*returnSize] = (int*)malloc(sizeof(int) * (preRear - head)); //记录当前行的各个结点的值
(*returnColumnSizes)[*returnSize] = preRear - head; //记录当前行的列数
int col = 0;
//遍历当前行
for (; head < preRear; head++) {
struct TreeNode* tmp = queue[head]; //出队
res[*returnSize][col++] = tmp->val; //将出队结点的值放入res对应行对应列的位置
//左右孩子入队
if (tmp->left) {
queue[rear++] = tmp->left;
}
if (tmp->right) {
queue[rear++] = tmp->right;
}
}
(*returnSize)++; //当前行处理完毕,行数+1
}
return res;
}
运行,测试通过