题目描述
请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
问题分析
二叉树的结构:
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
对这个问题进行分析,关键点有3个,第一是判断哪一层该怎么打印,我设根节点为第0层,则偶数层从左向右打印,奇数层从右向左打印。第二是采用什么数据结构实现左右打印。对于这个问题可以采用栈实现。第三打印结束的终止条件是什么。下面我会详细讲述。
我的代码及讲解
具体的讲解在代码的注释中,按步骤看还是比较清晰的,采用栈的结构可以很好地保证按顺序打印,奇数栈中pop出的元素的左右子树按从右向左的顺序压入偶数栈,偶数栈中的元素则相反。当奇数栈和偶数栈中的元素全部弹出意味着二叉树遍历完成。代码如下:
public class Solution {
public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
//存放偶数层的结点
Stack<TreeNode> stackEven=new Stack<>();
//存放奇数层的结点
Stack<TreeNode> stackOdd=new Stack<>();
ArrayList<ArrayList<Integer>> result=new ArrayList();
//层数,跟结点为0层
int count=0;
if(pRoot==null)return result;
//跟结点不为空时将其压入偶数栈中
stackEven.push(pRoot);
//循环打印的条件若栈中还有元素存在则遍历
while(!stackOdd.empty()||!stackEven.empty()){
//如果是偶数层
if(count%2==0){
ArrayList<Integer> arr=new ArrayList<>();
//偶数栈不为空
//偶数层将其子节点按照从左向右的顺序压入奇数栈可以保证奇数栈在pop时是从右向左的,既打印顺序从右向左。
while(!stackEven.empty()){
if(stackEven.peek().left!=null){
//当偶数栈顶元素左子结点不为空时压入奇数栈
stackOdd.push(stackEven.peek().left);
}
if(stackEven.peek().right!=null){
//当偶数栈顶元素右子结点不为空时压入奇数栈
stackOdd.push(stackEven.peek().right);
}
//将偶数栈顶弹出,将其val加入arr。
arr.add(stackEven.pop().val);
}
//层数加一
count++;
//当arr不为空时,将arr加入result
if(!arr.isEmpty())
result.add(arr);
}
if(count%2==1){
ArrayList<Integer> arr=new ArrayList<>();
//奇数栈不为空
//奇数层将其子节点按照从右向左的顺序压入偶数栈可以保证偶数栈在pop时是从左向右的,既打印顺序从左向右。
while(!stackOdd.empty()){
if(stackOdd.peek().right!=null){
stackEven.push(stackOdd.peek().right);
}
if(stackOdd.peek().left!=null){
stackEven.push(stackOdd.peek().left);
}
arr.add(stackOdd.pop().val);
}
count++;
if(!arr.isEmpty())
result.add(arr);
}
}
return result;
}
}
别人的代码
链接:https://www.nowcoder.com/questionTerminal/91b69814117f4e8097390d107d2efbe0?f=discussion
来源:牛客网
public static ArrayList<ArrayList<Integer>> Print(TreeNode pRoot){
int layer = 1;
//s1存奇数层节点
Stack<TreeNode> s1 = new Stack<TreeNode>();
s1.push(pRoot);
//s2存偶数层节点
Stack<TreeNode> s2 = new Stack<TreeNode>();
ArrayList<ArrayList<Integer>> list = new ArrayList<ArrayList<Integer>>();
while (!s1.empty() || !s2.empty()) {
if (layer%2 != 0) {
ArrayList<Integer> temp = new ArrayList<Integer>();
while (!s1.empty()) {
TreeNode node = s1.pop();
if(node != null) {
temp.add(node.val);
System.out.print(node.val + " ");
s2.push(node.left);
s2.push(node.right);
}
}
if (!temp.isEmpty()) {
list.add(temp);
layer++;
System.out.println();
}
} else {
ArrayList<Integer> temp = new ArrayList<Integer>();
while (!s2.empty()) {
TreeNode node = s2.pop();
if(node != null) {
temp.add(node.val);
System.out.print(node.val + " ");
s1.push(node.right);
s1.push(node.left);
}
}
if (!temp.isEmpty()) {
list.add(temp);
layer++;
System.out.println();
}
}
}
return list;
}
总结
第一次做这个题看了老半天,一头雾水,根本无从下手,解析都看了特别长时间,等到最近再捡起来,一下就有了思路,自己也能写出来,过程中出现了一些错误
//当arr不为空时,将arr加入result
if(!arr.isEmpty())
result.add(arr);
如果不加这句代码的话,会向result集合中加入一组空的arrlist,还是要注意,另外写代码的时间太长了,需要提高。继续加油,向各位大佬们学习。书山有路勤为径,