请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
在「把二叉树打印成多行」的基础上再添加一个判断条件:偶数行从右到左(当然,还有设置一个变量来记录当前所处的是第几行)
/*
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> > result = new ArrayList<>();
if(null == pRoot) return result;
Queue<TreeNode> q = new LinkedList<>();
q.offer(pRoot);
int level = 0; //记录当前层数为第0层
while(!q.isEmpty()){
ArrayList<Integer> list = new ArrayList<>(); //临时数组,每次存储一层
int levelSize = q.size(); //将当前层的元素个数记录下来,利用for循环一次存一层
for(int i = 0;i<levelSize;i++){
TreeNode head = q.peek();
list.add(head.val);
if(null != head.left) q.offer(head.left);
if(null != head.right) q.offer(head.right);
q.poll();
}
level++;
if(level %2 == 0) Collections.reverse(list); //层数为偶数,就从右往左
result.add(list);
}
return result;
}
}
上面的是利用Collections.reverse(list)
实现对不同的层正反存储。
下面使用ArrayList<>()
的 add(index,element)
方法实现,每次执行add(0,node.val)
会将新元素添加到0的位置,后面的元素会依次往后顺延。
public class Solution {
public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer> > result = new ArrayList<>();
if(pRoot == null) return result;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(pRoot);
boolean reverse = false; // 当前层数是否反转打印
while(!queue.isEmpty()){
int size = queue.size();
ArrayList<Integer> list = new ArrayList<>();
for(int i=0;i<size;i++){
TreeNode node = queue.poll();
if(!reverse){ // 如果 reverse==false
list.add(node.val);
}else{
list.add(0,node.val); // 每次加到 0 的位置,就自动逆序了
}
if(node.left != null) queue.offer(node.left);
if(node.right != null) queue.offer(node.right);
}
if(list.size() > 0){
result.add(list);
}
reverse = !reverse; // 每循环一层,逆序
}
return result;
}
}
数组的顺延的方式效率仍然是比较低,现在用两个栈来实现,我们在打印某一行结点时,把下一层的子结点保存到相应的栈里。如果当前打印的是奇数层,则先保存右子结点再保存左子结点到一个栈里;如果当前打印的是偶数层,则先保存左子结点再保存右子结点到第二个栈里。
时间复杂度:
O(n)
空间复杂度:O(n)
具体说:
设两个栈,s1
存放奇数层,s2
存放偶数层
- 遍历
s1
节点的同时按照右子树、左子树的顺序加入s2
- 遍历
s2
节点的同时按照左子树、右子树的顺序加入s1
public class Solution {
public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer> > result = new ArrayList<>();
if(pRoot == null) return result;
Stack<TreeNode> s1 = new Stack<>(); // q1存奇数层,左右
Stack<TreeNode> s2 = new Stack<>(); // q2存偶数层,右左
s2.push(pRoot);
int level = 0;
while(!s1.isEmpty() || !s2.isEmpty()){
if(level%2 == 0){ //当前层数为偶
int size2 = s2.size();
ArrayList<Integer> list2 = new ArrayList<>();
for(int i=0;i<size2;i++){
TreeNode node = s2.pop();
list2.add(node.val);
if(node.left != null) s1.push(node.left);
if(node.right != null) s1.push(node.right);
}
level++;
if(list2.size() > 0)result.add(list2);
}
if(level%2 == 1){ //当前层数为奇
int size1 = s1.size();
ArrayList<Integer> list1 = new ArrayList<>();
for(int i=0;i<size1;i++){
TreeNode node = s1.pop();
list1.add(node.val);
if(node.right != null) s2.push(node.right);
if(node.left != null) s2.push(node.left);
}
level++;
if(list1.size() > 0) result.add(list1);
}
}
return result;
}
}