剑指offer JZ77 之字形打印二叉树

JZ77 之字形打印二叉树

1.题目描述

在这里插入图片描述

2.解题思路

拿到这个题目,首先就发现这个题目和二叉树层序遍历非常像,但是存在区别,二叉树层序遍历是按照“从上到下,从左到右”的顺序一层层进行的。但是这个题目要求奇数层从左往右,偶数层从右往左。函数返回的结果是一个ArrayList<ArrayList>的对象,所以要考虑对偶数层次的遍历结果做一个反转,再add到返回的ArrayList里面。
反转的实现我自己的思路是这样的,通过一个队列和一个栈,偶数层的层序遍历结果就将其入栈再add进去,层次数用一个boolean标记isEven来实现。但是这个方法不算很优雅,而且需要一个栈和一个队列,所需的额外空间变多了。
然后看了下别人利用Deque的解法,深感巧妙,因为反转实际上就是输入顺序与输出顺序相反,那从队列一端入队,再从同一端出队是不是也可以?而且在某一层操作全部完成之前,不会对下一层做操作,可以很容易地区分不同层次,而不需要使用标记变量或者哨兵。那么使用双端队列,Deque可以实现这一操作,具体来说就是:对奇数层,将其按照普通层序遍历的规则遍历,从队头出队,下一层的结点按照从左往右的顺序从队列尾端插入。对偶数层,则从队尾出队,下一层结点按照从右往左的顺序从队头插入。

3.代码实现

import java.util.*;


/*
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) {
        Deque <TreeNode> deque = new LinkedList<>();
        ArrayList<ArrayList<Integer> > ret = new ArrayList<>();
        //当root结点不为空时,将其入队
        if(pRoot != null) 
            deque.offerLast(pRoot);
        while(!deque.isEmpty()) {
            // 打印奇数层
            //每个tmp存放一层的输出结果
            ArrayList <Integer> tmp = new ArrayList<>();
            //根据当前层结点数量确定操作
            for(int i = deque.size(); i > 0; i--) {
                // 从左向右输出,从队首出队
                TreeNode node = deque.removeFirst();
                tmp.add(node.val);
                // 先左后右顺序在队尾加入下层节点,先判断是否空
                if(node.left != null) 
                    deque.offerLast(node.left);
                if(node.right != null) 
                    deque.offerLast(node.right);
            }
            //把当前层的结果放到ret里
            ret.add(tmp);
            // 若队列为空说明树已经遍历完了,为空则提前跳出
            if(deque.isEmpty()) 
                break; 
            // 打印偶数层
            tmp = new ArrayList<>();
            //根据当前层结点数量确定操作
            for(int i = deque.size(); i > 0; i--) {
                // 从右向左输出,从队尾出队
                TreeNode node = deque.removeLast();
                tmp.add(node.val);
                // 按先右后左顺序在队头加入下层节点
                if(node.right != null) 
                    deque.offerFirst(node.right);
                if(node.left != null) 
                    deque.offerFirst(node.left);
            }
            //把当前层的结果放到ret里
            ret.add(tmp);
        }
        return ret;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值