标签:node tmp JZ deque 32 打印 二叉树 res 节点
目录
题目
在【JZ-32-II】的基础上,要求打印每一层的方向交替变化,即,奇数层正序打印,偶数层倒序打印。
参考
方法一-层序遍历+双端队列
算法思路
算法流程:
1. 特例处理: 根节点
r
o
o
t
root
root 为空时,直接返回空列表
2. 初始化: 结果列表
r
e
s
res
res 和 包含根节点的双端队列
d
e
q
u
e
deque
deque
3. BFS循环,当队列
d
e
q
u
e
deque
deque 为空时跳出循环:
- 新建一个临时列表 t m p tmp tmp,用来存储当前这层的打印结果;
- 当前层打印循环(循环次数为当前层节点数,即
d
e
q
u
e
deque
deque 长度):
队首元素出队,记为 n o d e node node;
打印该元素,若为奇数层,则将 n o d e . v a l node.val node.val 添加到列表 t m p tmp tmp 尾部;若为偶数层,则将 n o d e . v a l node.val node.val 添加到列表 t m p tmp tmp 头部;
若 n o d e node node 的左右子节点不为空,则将子节点加入队列 d e q u e deque deque - 将当前层打印结果 t m p tmp tmp 转化为 list 并添加到结果列表 r e s res res
4. 返回值: 结果列表 r e s res res
关于如何判断奇数层还是偶数层:
res.size()为偶数时,当前层为奇数层; res.size()为奇数时,当前层为偶数层
具体代码
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
Deque<TreeNode> deque = new LinkedList<>();//双端队列初始化
List<List<Integer>> res = new ArrayList<>();//结果列表初始化
if(root != null)deque.offerLast(root);//根节点尾部入队
while(!deque.isEmpty()){
LinkedList<Integer> tmp = new LinkedList<>();//临时列表,存储当前层的打印结果
for(int i = deque.size(); i > 0; i--){
TreeNode node = deque.pollFirst();//队首元素出队
if(res.size() % 2 == 0)tmp.offerLast(node.val);//奇数层,列表尾部添加
else tmp.offerFirst(node.val);//偶数层,列表头部添加
//子节点入队
if(node.left != null)deque.offerLast(node.left);
if(node.right != null)deque.offerLast(node.right);
}
res.add(tmp);//当前层打印结果添加到结果列表
}
return res;
}
}
复杂度分析
- 时间复杂度: O ( n ) O(n) O(n),n 为二叉树节点总数。因为 BFS 需要循环 n 次,双端队列的队首和队尾添加操作、删除操作的时间复杂度均为 O ( 1 ) O(1) O(1)
- 空间复杂度: O ( n ) O(n) O(n),因为在最坏情况下,即,树为平衡二叉树时,最多会有 n / 2 n/2 n/2 个节点同时在队列 d e q u e deque deque 中,占用了 O ( n ) O(n) O(n) 大小的额外空间。
方法二-奇偶层逻辑分离
算法思路
在方法一的基础上,将奇偶层逻辑拆分,消除冗余的判断(方法一中需要判断每一个节点所在层的奇偶性)
算法流程(只有BFS循环部分与方法一不同):
BFS循环,当队列 d e q u e deque deque 为空时跳出循环:
- 打印奇数层:从左向右打印,先左后右加入下层节点;
- 打印偶数层:从右向左打印,先右后左加入下层节点;
具体代码
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
Deque<TreeNode> deque = new LinkedList<>();//双端队列初始化
List<List<Integer>> res = new ArrayList<>();//结果列表初始化
if(root != null)deque.offerLast(root);//根节点尾部入队
while(!deque.isEmpty()){
//打印奇数层
LinkedList<Integer> tmp = new LinkedList<>();//临时列表,存储当前层的打印结果
for(int i = deque.size(); i > 0; i--){
//从左向右打印
TreeNode node = deque.pollFirst();//队首元素出队
tmp.offerLast(node.val);
//先左后右加入下层节点
if(node.left != null)deque.offerLast(node.left);
if(node.right != null)deque.offerLast(node.right);
}
res.add(tmp);//当前层打印结果添加到结果列表
if(deque.isEmpty())break;//若队列为空提前跳出
//打印偶数层
tmp = new LinkedList<>();
for(int i = deque.size(); i > 0; i--){
//从右向左打印
TreeNode node = deque.pollLast();//队尾元素出队
tmp.offerLast(node.val);
//先右后左加入下层节点
if(node.right != null)deque.offerFirst(node.right);
if(node.left != null)deque.offerFirst(node.left);
}
res.add(tmp);//当前层打印结果添加到结果列表
}
return res;
}
}
复杂度分析
同方法一
方法三-层序遍历+倒序
算法思路
将偶数层中的元素倒序
具体代码
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
Deque<TreeNode> deque = new LinkedList<>();//双端队列初始化
List<List<Integer>> res = new ArrayList<>();//结果列表初始化
if(root != null)deque.offerLast(root);//根节点尾部入队
while(!deque.isEmpty()){
//打印奇数层
LinkedList<Integer> tmp = new LinkedList<>();//临时列表,存储当前层的打印结果
for(int i = deque.size(); i > 0; i--){
TreeNode node = deque.pollFirst();//队首元素出队
tmp.offerLast(node.val);
//加入下层节点
if(node.left != null)deque.offerLast(node.left);
if(node.right != null)deque.offerLast(node.right);
}
if(res.size() % 2 == 1)Collections.reverse(tmp);//偶数层倒序
res.add(tmp);//当前层打印结果添加到结果列表
}
return res;
}
}
复杂度分析
- 时间复杂度: O ( n ) O(n) O(n),n 为二叉树节点总数。因为 BFS 需要循环 n 次,占用 O ( n ) O(n) O(n);一共进行了少于 n 个节点的倒序操作,占用 O ( n ) O(n) O(n)。
- 空间复杂度: O ( n ) O(n) O(n),因为在最坏情况下,即,树为满二叉树时,最多会有 n / 2 n/2 n/2 个节点同时在队列 d e q u e deque deque 中,占用了 O ( n ) O(n) O(n) 大小的额外空间。
标签:node,tmp,JZ,deque,32,打印,二叉树,res,节点 来源: https://blog.csdn.net/qq_38001377/article/details/114701955
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。