题目描述
请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
思路分析
我们可以注意到当前行为奇数行下一行是从右到左进行访问的,当前行为偶数行是从左到右访问的,呈现的效果是加入的顺序和访问的顺序是相反的,所以我们首先想到利用栈来进行存储。根据前面的从上到下分行打印,我们知道如何进行换行和计算下一行的的节点个数,再添加一个变量curLine
表示当前是那行,根据该变量确认如何添加下一行的元素;
总结出规律:按之字形打印二叉树我们需要两个栈,在打印某一层结点时,把下一层的子结点保存到相应栈中。如果是奇数层,则先保存左结点再保存右结点,这样换下一行访问时就是先右后左。如果是偶数层,则先保存右结点再保存左结点,访问就是从左到右。例如上图第一行用奇数栈保存C E
,当换到下一行时,弹出顺序即访问顺序是E C
,第二行用偶数栈保存G H D A
然后换行,当再次换行时,弹出访问顺序是A F H G
,呈现之字形打印效果;
代码实现
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Stack;
/*
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
if (pRoot == null) {
return res;
}
int toBeLine = 1, nextLine = 0, curLine = 1;
TreeNode treeNode;
ArrayList<Integer> row = new ArrayList<>();
Stack<TreeNode> oddStack = new Stack<>();
Stack<TreeNode> evenStack = new Stack<>();
///第一个元素
evenStack.push(pRoot);
while (!oddStack.isEmpty() || !evenStack.isEmpty()) {
treeNode = curLine % 2 == 0 ? oddStack.pop() : evenStack.pop();
row.add(treeNode.val);
if (curLine % 2 == 1) {
///奇数行从左到右入栈
if (treeNode.left != null) {
oddStack.push(treeNode.left);
nextLine++;
}
if (treeNode.right != null) {
oddStack.push(treeNode.right);
nextLine++;
}
} else {
///偶数行从右到左入栈
if (treeNode.right != null) {
evenStack.add(treeNode.right);
nextLine++;
}
if (treeNode.left != null) {
evenStack.add(treeNode.left);
nextLine++;
}
}
--toBeLine;
///换行
if (toBeLine == 0) {
curLine++;
toBeLine = nextLine;
nextLine = 0;
res.add(row);
row = new ArrayList<>();
}
}
return res;
}
}