Skip to content

Commit 5232243

Browse files
author
Longerhaha
authored
提交103_二叉树的锯齿形层次遍历
添加题解103_(二叉树的锯齿形层次遍历)Binary Tree Zigzag Level Order Traversal
1 parent 33a51c4 commit 5232243

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
## 103_(二叉树的锯齿形层次遍历)Binary Tree Zigzag Level Order Traversal
2+
## 1 问题描述、输入输出与样例
3+
### 1.1 问题描述
4+
给定一个二叉树,返回其节点值的锯齿形层次遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。<br>
5+
### 1.2 输入与输出
6+
输入:<br>
7+
* TreeNode* root:二叉树的根节点指针<br>
8+
输出:<br>
9+
* vector<vector<int>>:锯齿形层次遍历的结果,是一个二维矢量的形式
10+
### 1.3 样例
11+
#### 1.3.1 样例1
12+
输入: 给定二叉树: [3,9,20,null,null,15,7],
13+
14+
3
15+
/ \
16+
9 20
17+
/ \
18+
15 7
19+
20+
输出:
21+
22+
[
23+
[3],
24+
[20,9],
25+
[15,7]
26+
]
27+
28+
## 2 思路描述与代码
29+
### 2.1 思路描述(基于队列的二叉树层次遍历)
30+
二叉树的层次遍历可以利用队列来做,其思路也很简单。<br>
31+
这里为了把每层的结果记录下来,对BFS的代码结构稍微改动了下,即里面用了个 for 循环做当前层遍历。<br>
32+
其次与102层次遍历不一样的是,这里使用 depth 记录深度,在深度 depth 为偶数的时候对当前层次遍历结果进行反转再插入 res 中。
33+
```cpp
34+
初始化二叉树层次遍历的二维矢量 res ;
35+
头结点入队;
36+
深度初始化为0;
37+
while( 队列不空 ){
38+
初始化当前层的遍历结果 level;
39+
获取当前层的数目数 len;
40+
for( int i = 0; i < len; i++ ){
41+
取出当前层的节点tmp并保存至 level;
42+
左右孩子非空则入队;
43+
}
44+
如果深度为偶数则反转 level;
45+
将 level 保存至 res ;
46+
}
47+
返回 res ;
48+
```
49+
比如给定二叉树: [3,9,20,null,null,15,7];<br>
50+
首先根节点3入队,然后进入 while 循环;<br>
51+
此时队列不空,深度为1,有1个元素3,for 循环后有 res = {[3]}, 队列里面有元素[9, 20];<br>
52+
此时队列不空,深度为2,有元素[9, 20],反转后为[20, 9], for 循环后有 res = {[3],[20,9]}, 队列里面有元素[15, 7];<br>
53+
此时队列不空,深度为3,有元素[15, 7],for 循环后有 res = {[3],[20,9], [15,7]}, 队列里面没有元素;<br>
54+
此时队列空后,返回 res = {[3],[20,9], [15,7]} 。
55+
56+
### 2.2 代码
57+
```cpp
58+
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
59+
vector<vector<int>> res;
60+
if(root == nullptr)
61+
return res;
62+
//基于队列做层序遍历
63+
queue<TreeNode*> q;
64+
q.push(root);
65+
//层序遍历的深度
66+
int depth = 1;
67+
while( !q.empty() ){
68+
//保存当前层遍历的结果
69+
vector<int> layer;
70+
//获取当前层的节点数目
71+
int layer_size = q.size();
72+
//遍历当前的所有层
73+
for( int i = 0; i < layer_size; i++ ){
74+
TreeNode* tmp = q.front();
75+
q.pop();
76+
//如果左右子树非空,则入队
77+
if(tmp->left)
78+
q.push(tmp->left);
79+
if(tmp->right)
80+
q.push(tmp->right);
81+
layer.push_back(tmp->val);
82+
}
83+
//将当前层遍历的结果存到res里面,同时深度加1
84+
if((depth & 0x01) == 0) reverse(layer.begin(), layer.end());
85+
res.push_back(layer);
86+
depth += 1;
87+
}
88+
return res;
89+
}
90+
```
91+
## 3 思考与拓展
92+
### 3.1 思考
93+
本题,主要考察的还是数据结构。这里为了简单,直接对深度为偶数层的遍历结果直接反转。你也可以使用双端队列或者奇层用队列、偶层用堆栈。
94+
#### 3.1.1 其他方法
95+
#### 3.1.1.1 基于双端队列的二叉树锯齿形层次遍历
96+
思路还是一致的,只是数据结构换了而已。<br>
97+
在 depth 为奇数的时候从队头出队;<br>
98+
在 depth 为偶数的时候从队尾出队;<br>
99+
#### 3.1.2 复杂度分析
100+
方法|空间复杂度|时间复杂度
101+
--- | --- | ---
102+
基于队列的二叉树层次遍历|O(2^h),h是树的高度|O(n)
103+
基于双端队列的二叉树锯齿形层次遍历|O(2^h),h是树的高度|O(n),由于不需要反序,所以会比基于队列的二叉树层次遍历快一点
104+
#### 3.1.3 难点分析
105+
1. 采用何种数据结果保存不同方式的层遍历结果
106+
### 3.2 拓展
107+
如果让你结合队列和堆栈做锯齿形层次遍历呢?

0 commit comments

Comments
 (0)