题解 | #二叉树的之字形层序遍历#
二叉树的之字形层序遍历
http://www.nowcoder.com/practice/47e1687126fa461e8a3aff8632aa5559
题目:二叉树的之字形层序遍历
描述:给定一个二叉树,返回该二叉树的之字形层序遍历,(第一层从左向右,下一层从右向左,一直这样交替)
例如:给定的二叉树是{3,9,20,#,#,15,7},
该二叉树之字形层序遍历的结果是[ [3], [20,9], [15,7] ]
示例1:输入:{1,#,2},返回值:[[1],[2]]
解法一:
思路分析:因为是要将二叉树进行之字形层序遍历,所以我们采用双栈进行,排序规则为第一层通过正序输出,第二层逆序输出,第三层正序输出,通过依次类推,实现之字形排序,使用栈的性质(先进后出),先进入栈的数据最后再出栈,为了能够实现逆序遍历,将二叉树的第二层结点保存在栈1中,重新设置栈2存储下一层结点,使用stackout表示存储当前层结点的栈。stackIn表示存储下一层节点的栈,从左往右遍历(正向遍历)时,需要存储当前节点的左节点stackIn中;从右往左遍历(反向遍历)时,需要存储当前节点的右节点stackIn中
实例分析:以二叉树{3,9,20,#,#,15,7}为例,将根节点3存入stack1中,首先遍历的方向为从左往右遍历,其中stack1为stackout,stack2为stackin,当遍历完成后,stack1为空,stack2中存储着第二层的结点,遍历时需要不断pop出stackout中的结点,添加到arraylist中,从而可以得到第一层的顺序遍历。
| 树: |
| —> | 3 | 将3存入stack1中 | ||
|
| 9 |
| 20 | stack2 | ||
| 15 |
| 7 |
|
|
|
|
当遍历完第一层后,将方向反转,变为从右往左遍历,此时stack2为stackout,stack1为stackin,遍历完成后stack2为空,stack1中存储着第三层的结点,还是需要不断的pop出stackout中的结点,添加到arraylist中,得到第二层的逆序遍历。
| 树: |
|
| 3 |
| ||
|
| 9 |
| 20 | <—stack2 | ||
| 15 |
| 7 |
|
|
| stack3 |
依次类推,返回最终值[ [3], [20,9], [15,7] ]。
Java代码为:
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* }
*/
public class Solution {
/**
*
* @param root TreeNode类
* @return int整型ArrayList<arraylist><>>
*/
public ArrayList zigzagLevelOrder (TreeNode root) {
// write code here
ArrayList cache = new ArrayList<>();
if(root == null)
return cache;
Deque stack1 = new LinkedList<>();//设置双栈
Deque stack2 = new LinkedList<>();
stack1.push(root);//将根节点压入栈1
boolean isfound = true;//设置方向
while(stack1.isEmpty() == false || stack2.isEmpty() == false){//当前栈是否还有元素
DequestackOut = stack1.isEmpty() ? stack2 : stack1;
DequestackIn = stack1.isEmpty() ? stack1 : stack2;
//stackout存储当前层,stackin存储下一层
cache.add(new ArrayList<>());
//遍历当前层的结点
while(stackOut.isEmpty() == false){
//栈顶出栈
TreeNode cur = stackOut.pop();
//添加到Arraylist里边
cache.get(cache.size() - 1).add(cur.val);
if (isfound) {
//如果方向是从左往右,则先遍历当前节点的左节点
pushNode(stackIn, cur.left);
pushNode(stackIn, cur.right);
}
else {
//如果方向是从右往左,则先遍历当前节点的右节点
pushNode(stackIn, cur.right);
pushNode(stackIn, cur.left);
}
}
isfound = !isfound;//改变方向
}
return cache;
}
private void pushNode(Dequestack, TreeNode node) {//将结点存入栈中
if (node != null) {
stack.push(node);
}
}
}</arraylist>
遍历树中的每一个元素,时间复杂度为O(N),空间复杂度为O(N)。
解法二:
思路分析:首先创建队列,将结点加入到队列当中,利用先进先出原则,依次弹出栈。将每次弹出结点的值保存到链表当中,如果是奇数层的话,就采用尾插,如果为偶数层的话,执行头插,如果弹出的结点中有左右子树,则将左右子结点加入到当前队列当中,在每一层遍历完成后都要将这一层的结点加入到链表当中。
| 树: |
|
| 3(头插) |
| ||
|
| 9 |
| 20 | (尾插) | ||
| 15 |
| 7 |
|
|
| (头插) |
| 返回最终值[ [3], [20,9], [15,7] ] | ||||||
具体Java代码为:
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* }
*/
public class Solution {
/**
*
* @param root TreeNode类
* @return int整型ArrayList<arraylist><>>
*/
public ArrayList zigzagLevelOrder (TreeNode root) {
ArrayList res = new ArrayList<>();
Queueque = new LinkedList<>();//创建队列
if(root != null){
que.add(root);
}
while(!que.isEmpty()){
ArrayListtmp = new ArrayList<>();//存储每一层节点
for(int i = que.size();i > 0;i--){//遍历当前层的节点
TreeNode node = que.poll();//弹出队列中的节点
if((res.size() + 1) % 2 != 0){
tmp.add(node.val);//奇数尾插
}
else{
tmp.add(0,node.val);//偶数层头插
}
if(node.left!=null){//如果左子节点不为空,则将其加入到队列中
que.add(node.left);
}
if(node.right!=null){//如果右子节点不为空,则将其加入到队列中
que.add(node.right);
}
}
res.add(tmp);//将这一层的节点加入到res中
}
return res;
}
}</arraylist>
其时间复杂度为O(N),设置链表对象和队列用与存储数字,所以其空间复杂度为O(N)。
在解决问题的同时,不断与人交流学习,通过牛客各式各样的题目,学习分享。
360集团公司氛围 376人发布