剑指offer:JZ59 按之字形顺序打印二叉树

描述

给定一个二叉树,返回该二叉树的之字形层序遍历,(第一层从左向右,下一层从右向左,一直这样交替)
例如:给定的二叉树是{1,2,3,#,#,4,5},该二叉树之字形层序遍历的结果是[[1],[3,2],[4,5]]

1
2
3
4
5
/* TreeNode类的代码
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;
    public TreeNode(int val) {
        this.val = val;
    }
}
*/

示例

input1:
{8,6,10,5,7,9,11}
output1:
[[8],[10,6],[5,7,9,11]]

input2:
{1,2,3,4,5}
output2:
[[1],[3,2],[4,5]]

思路

根据题目的要求,需要对二叉树进行层序遍历同时区分奇偶层。该题的要点为:保存每一层的结果(从1开始),保存的顺序为:奇数层从左往右,偶数层从右到左。按照该要点,可以考虑以下方法:

  • 使用队列:Queue保存每一层的结果,每次遍历将poll出当前层个数的结点,另外需要使用一个deep记录层数:奇数层调用Array.add(e)达到从左到右,偶数层调用Array.add(e)然后Collections.reverse(arr)进行反序达到从右到左的顺序
  • 使用双栈:一个保存奇数层,一个保存偶数层

1、单向队列:偶数层反序

该方法参考 剑指offer:JZ60 把二叉树打印成多行 该题目中也可以使用ArrayList.add(0, e)来达到反序的目的,但是ArrayList中数组整体移动的次数较多。

import java.util.*;
public class Solution {
    public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> list = new ArrayList<>();
        if(pRoot == null) return list;
        TreeNode tmp = null;
        int size = 0, i = 0, deep = 1;
        Queue<TreeNode> que = new LinkedList<>();
        ArrayList<Integer> arr = null;
        que.offer(pRoot);
        while(!que.isEmpty()){
            size = que.size();//获取当前层的结点个数
            i = 0;
            arr = new ArrayList<>();
            while(i++ < size){
                tmp = que.poll();
                arr.add(tmp.val);
                if(tmp.left != null) que.offer(tmp.left);
                if(tmp.right != null) que.offer(tmp.right);
            }
            if((deep & 1) == 0) Collections.reverse(arr);
            list.add(arr);
            deep++;
        }
        return list;
    }
}

在这里插入图片描述

2、双端队列:奇偶分离

双端队列可以保证奇数层时从队头取结点,偶数层时从队尾取元素。

import java.util.*;
public class Solution {
    public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> list = new ArrayList<>();
        if(pRoot == null) return list;
        TreeNode tmp = null;
        int size = 0, i = 0, deep = 1;
        Deque<TreeNode> deque = new LinkedList<>();
        ArrayList<Integer> arr = null;
        deque.offer(pRoot);
        while(!deque.isEmpty()){
            size = deque.size();//获取当前层的结点个数
            i = 0;
            arr = new ArrayList<>();
            while(i++ < size){
                if((deep & 1) == 1){//奇数层
                    tmp = deque.removeFirst();
                    if(tmp.left != null) deque.addLast(tmp.left);
                    if(tmp.right != null) deque.addLast(tmp.right);
                }
                else{
                    tmp = deque.removeLast();
                    if(tmp.right != null) deque.addFirst(tmp.right);
                    if(tmp.left != null) deque.addFirst(tmp.left);
                }
                arr.add(tmp.val);
            }
            list.add(arr);
            deep++;
        }
        return list;
    }
}

在这里插入图片描述

3、双栈:奇偶层分离

该方法利用栈的特性:先进后出。因此按照奇偶栈可以实现本题:
(1)奇数栈加入根结点,当前深度设为1。
(2)当前循环为奇数层,则遍历奇数栈中元素,同时按照从左到右的顺序将下一层结点加入到偶数栈(因而偶数栈遍历时结点从右到左)
(3)当前循环为偶数层,则遍历偶数栈中元素,同时按照从右到左的顺序将下一层结点加入到奇数栈(因而奇数栈遍历时结点从左到右)

import java.util.*;
public class Solution {
    public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> list = new ArrayList<>();
        if(pRoot == null) return list;
        TreeNode tmp = null;
        int size = 0, i = 0, deep = 1;
        Stack<TreeNode> st_odd = new Stack<>();
        Stack<TreeNode> st_even = new Stack<>();
        ArrayList<Integer> arr = null;
        st_odd.push(pRoot);
        while(!st_odd.isEmpty() || !st_even.isEmpty()){
            i = 0;
            arr = new ArrayList<>();
            if((deep & 1) == 1){//奇数层
                size = st_odd.size();
                while(i++ < size){
                    tmp = st_odd.pop();
                    arr.add(tmp.val);
                    //下一层是偶数层,因此偶数栈先加左子树,保证右边的结点在栈顶
                    if(tmp.left != null) st_even.push(tmp.left);
                    if(tmp.right != null) st_even.push(tmp.right);
                }
            }
            else{//偶数层
                size = st_even.size();
                while(i++ < size){
                    tmp = st_even.pop();
                    arr.add(tmp.val);
                    //下一层是奇数层,因此奇数栈先加右子树,保证左边的结点在栈顶
                    if(tmp.right != null) st_odd.push(tmp.right);
                    if(tmp.left != null) st_odd.push(tmp.left);
                }
            }
            list.add(arr);
            deep++;
        }
        return list;
    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值