这是我参与2022首次更文挑战的第17天,活动详情查看:2022首次更文挑战
给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。
输入:root = [3,9,20,null,null,15,7] 输出: [[3],[20,9],[15,7]]
首先,我先声明这和昨天的可不是一道题属于他的一个变种,如果做过昨天的那道题,今天的题应该很容易就像出来
没看过的同学大家可以先参考一下,二叉树的层序遍历
我们分析一下我们这两道题具体是有什么区别呢?
一个是层序遍历,一个是锯齿形层序,我们特殊的地方就是我们我们每一层都要换一个方向,首先,大家不要进入一个误区,就是让我们的遍历顺序按照我们输出的方式去遍历,那我们做起来就会很麻烦,我看到这道题第一个想法就是,我们利用上一道题的遍历顺序,我们在装入list集合的时候我们呢反着装不就可以了?那怎么把一个集合反转呢?我一个想到的就是一种数据结构——栈,先入栈,在出栈,存入集合,完美!
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> result =new LinkedList<List<Integer>>();
if(root==null){
return result;
}
Queue<TreeNode> nodeQueue = new LinkedList<TreeNode>();
nodeQueue.add(root);
//控制反转
boolean q = true;
while (!nodeQueue.isEmpty()){
List<Integer> list = new ArrayList<Integer>();
Stack<Integer> stack = new Stack<Integer>();
int size = nodeQueue.size();
for (int i = 0; i < size; i++){
TreeNode node = nodeQueue.poll();
//需要反转的时候使数据入栈
if(!q){
stack.push(node.val);
}else {
list.add(node.val);
}
if(node.left!=null){
nodeQueue.offer(node.left);
}
if (node.right != null) {
nodeQueue.offer(node.right);
}
}
//相同条件判断,使数据出栈,存入集合
if(!q){
int s = stack.size();
for (int i = 0; i < s; i++){
list.add(stack.pop());
}
}
result.add(list);
q=!q;
}
return result;
}
但是,之后我去看了一下官方文档,去学习一下,唉,这一看不得了,我发现原来有一种数据结构叫做双向队列,他和队列的区别就是它两端都可以进出,虽然之前学过,可是忘没了,如果我们使用双向队列来做,代码就更加简单了
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> result =new LinkedList<List<Integer>>();
if(root==null){
return result;
}
Queue<TreeNode> nodeQueue = new LinkedList<TreeNode>();
nodeQueue.add(root);
boolean q = true;
while (!nodeQueue.isEmpty()){
Deque<Integer> deque = new LinkedList<Integer>();
int size = nodeQueue.size();
for (int i = 0; i < size; i++){
TreeNode node = nodeQueue.poll();
//根据判断符号来控制从前后入队
if(!q){
deque.addFirst(node.val);
}else {
deque.addLast(node.val);
}
if(node.left!=null){
nodeQueue.offer(node.left);
}
if (node.right != null) {
nodeQueue.offer(node.right);
}
}
result.add(new LinkedList<Integer>(deque));
q=!q;
}
return result;
}
两种解法,执行用时和内存消耗都差不多,对于我使用栈的方式将他倒转,我们会多开辟一块空间用来存储我们的栈,如果使用双向队列就会节省一部分空间,还是建议使用双向队列。
最后,对于为什么我们在把我们双线队列填入我们result的时候需要new LinkedList?
因为我们的队列不是集合我们的类型不同不能直接装入,虽然都是LinkedList实现,这涉及到泛型问题,大家可以搜一搜,解释的都比我好。