请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
lee上大神操作 用两个stack
1.遍历第二层的节点的顺序是从左到右,而输出第二层节点的顺序是从右到左,这正好满足栈思想,所有用栈来第二层所有节点。
2.遍历栈输出第二层节点,同时还需要将第三层的节点按照从右到左的顺序存储。但是不能将第三层的节点存储到这个栈中,因为会打乱第二层节点的顺序,此时我们可以想到创建另一个栈来存储第三层的元素。这样层与层之间就不会产生干扰。
3.交替使用这两个栈遍历所有的层。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> list = new ArrayList<>();
if (root == null) {
return list;
}
//栈1来存储右节点到左节点的顺序
Stack<TreeNode> stack1 = new Stack<>();
//栈2来存储左节点到右节点的顺序
Stack<TreeNode> stack2 = new Stack<>();
//根节点入栈
stack1.push(root);
//每次循环中,都是一个栈为空,一个栈不为空,结束的条件两个都为空
while (!stack1.isEmpty() || !stack2.isEmpty()) {
List<Integer> subList = new ArrayList<>(); // 存储这一个层的数据
TreeNode cur = null;
if (!stack1.isEmpty()) { //栈1不为空,则栈2此时为空,需要用栈2来存储从下一层从左到右的顺序
while (!stack1.isEmpty()) { //遍历栈1中所有元素,即当前层的所有元素
cur = stack1.pop();
subList.add(cur.val); //存储当前层所有元素
if (cur.left != null) { //左节点不为空加入下一层
stack2.push(cur.left);
}
if (cur.right != null) { //右节点不为空加入下一层
stack2.push(cur.right);
}
}
list.add(subList);
}else {//栈2不为空,则栈1此时为空,需要用栈1来存储从下一层从右到左的顺序
while (!stack2.isEmpty()) {
cur = stack2.pop();
subList.add(cur.val);
if (cur.right != null) {//右节点不为空加入下一层
stack1.push(cur.right);
}
if (cur.left != null) { //左节点不为空加入下一层
stack1.push(cur.left);
}
}
list.add(subList);
}
}
return list;
}
}
我写的,有问题 看不出来
class Solution {
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> res=new ArrayList<>();
if(root==null) return res;
Stack<TreeNode> stack1 = new Stack<>();
Stack<TreeNode> stack2 = new Stack<>();
stack1.push(root);
while(!stack1.isEmpty() || !stack2.isEmpty()){
List<Integer> list=new ArrayList<>();
TreeNode cur=null;
if(!stack1.isEmpty()){
while(!stack1.isEmpty()){
cur=stack1.pop();
list.add(cur.val);
if(cur.left!=null){
stack2.push(cur.left);
}
if(cur.right!=null){
stack2.push(cur.right);
}
}
res.add(list);
}else{
while(!stack2.isEmpty()){
cur=stack2.pop();
list.add(cur.val);
if(cur.left!=null){
stack1.push(cur.left);
}
if(cur.right!=null){
stack1.push(cur.right);
}
}
res.add(list);
}
}
return res;
}
}
不太优雅
看别人的:
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
if (root == null) return res;
Stack<TreeNode> stack1 = new Stack<>();
Stack<TreeNode> stack2 = new Stack<>();
stack1.push(root);
int count = 1;
while (!stack1.isEmpty() || !stack2.isEmpty()) {
ArrayList<Integer> list = new ArrayList<>();
if (count % 2 == 1) {//取出来,先存左儿子,再存右儿子
while (!stack1.isEmpty()) {
TreeNode tmp = stack1.pop();
list.add(tmp.val);
if (tmp.left != null) stack2.push(tmp.left);
if (tmp.right != null) stack2.push(tmp.right);
}
} else {//取出来,先存右儿子,再存左儿子
while (!stack2.isEmpty()) {
TreeNode tmp = stack2.pop();
list.add(tmp.val);
if (tmp.right != null) stack1.push(tmp.right);
if (tmp.left != null) stack1.push(tmp.left);
}
}
count++;
res.add(list);
}
return res;
}
}
前序遍历递归
可以这么写:
class Solution {
List<List<Integer>> res=new ArrayList<>();
public List<List<Integer>> levelOrder(TreeNode root) {
helper(root,0);
return res;
}
private void helper(TreeNode root,int level){
if(root==null)
return;
if(res.size()==level){
res.add(new ArrayList<>());
}
if(level%2==0){
res.get(level).add(root.val);
}else{
res.get(level).add(0,root.val);
}
helper(root.left,level+1);
helper(root.right,level+1);
}
}
这个也比较麻烦 算了思路
大家的实现很多都是将每层的数据存进ArrayList中,偶数层时进行reverse操作,
在海量数据时,这样效率太低了。
(我有一次面试,算法考的就是之字形打印二叉树,用了reverse,
直接被鄙视了,面试官说海量数据时效率根本就不行。)
- 下面的实现:不必将每层的数据存进ArrayList中,偶数层时进行reverse操作,直接按打印顺序存入
- 思路:利用Java中的LinkedList的底层实现是双向链表的特点。
1)可用做队列,实现树的层次遍历
2)可双向遍历,奇数层时从前向后遍历,偶数层时从后向前遍历
public class Solution {
public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer>> ret = new ArrayList<>();
if (pRoot == null) {
return ret;
}
ArrayList<Integer> list = new ArrayList<>();
LinkedList<TreeNode> queue = new LinkedList<>();
queue.addLast(null);//层分隔符
queue.addLast(pRoot);
boolean leftToRight = true;
while (queue.size() != 1) {
TreeNode node = queue.removeFirst();
if (node == null) {//到达层分隔符
Iterator<TreeNode> iter = null;
if (leftToRight) {
iter = queue.iterator();//从前往后遍历
} else {
iter = queue.descendingIterator();//从后往前遍历
}
leftToRight = !leftToRight;
while (iter.hasNext()) {
TreeNode temp = (TreeNode)iter.next();
list.add(temp.val);
}
ret.add(new ArrayList<Integer>(list));
list.clear();
queue.addLast(null);//添加层分隔符
continue;//一定要continue
}
if (node.left != null) {
queue.addLast(node.left);
}
if (node.right != null) {
queue.addLast(node.right);
}
}
return ret;
}
}