剑指offer面试题32(java版):从上到下打印二叉树

welcome to my blog

剑指offer面试题32(java版):从上到下打印二叉树

题目一

从上往下打印出二叉树的每个节点,同层节点从左至右打印。

笔记

  • Deque类是接口, 不能实例化, 需要借助实现了Deque接口的子类, 比如LinkedList. 如下
  • Deque d = new LinkedList();
  • 不要忘记引入import java.util.Deque;和 import java.util.LinkedList;
  • 从上到下按层遍历二叉树, 本质上讲就是广度优先遍历二叉树
  • 不管是广度优先遍历一幅有向图还是一棵树, 都要用到队列
  • 整体流程:
    • 首先把起始节点(对于树来说是根节点)放入队列.
    • 接下来每次从队列的头部取出一个节点, 遍历这个节点之后把该节点能到达的节点(对树来说是子节点)都依次放入队列
    • 重复上面这个遍历过程, 直到队列中的节点全部被遍历完

思路

  • 本题并不是前中后序遍历, 而是广度优先遍历
  • 借助队列这个数据结构实现遍历: 将出队的节点左右子节点(如果有的话)加入队列末尾
  • 记得检查当前出队的节点是否存在左右子节点, 有的话才将子节点加入队列
第二次做, 使用队列先进先出的特点
import java.util.ArrayList;
import java.util.LinkedList;

public class Solution {
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        ArrayList<Integer> al = new ArrayList<>();
        LinkedList<TreeNode> ll = new LinkedList<>();
        if(root==null)
            return al;
        //
        ll.add(root);
        TreeNode curr;
        while(!ll.isEmpty()){
            curr = ll.poll();
            al.add(curr.val);
            //whether has left child
            if(curr.left!=null)
                ll.add(curr.left);
            //whether has right child
            if(curr.right!=null)
                ll.add(curr.right);
        }
        return al;
    }
}
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;

public class Solution {
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        //execute
        ArrayList<Integer> al = new ArrayList<Integer>();
        if(root == null) // input check
            return al;
        Deque<TreeNode> d = new LinkedList<TreeNode>();
        TreeNode curr = null;
        d.addLast(root);
        while(!d.isEmpty()){
            curr = d.pollFirst(); 
            al.add(curr.val);
            if(curr.left != null)//不要忘记队列中添加null
                d.addLast(curr.left); 
            if(curr.right != null)
                d.addLast(curr.right);
        }
        return al;
    }
}

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/

题目二

分行从上到下打印二叉树
从上到下按层打印二叉树, 同一层的节点按从左到右地顺序打印, 每一层打印到一行.

思路

  • 需要两个变量toBePrinted, nextLevel
  • toBePrinted表示当前层中待打印的节点数量
  • nextLevel表示下一层中的元素的数量
第二次做; 层序遍历,使用队列; while中的初始化操作很关键
import java.util.ArrayList;
import java.util.LinkedList;

public class Solution {
    ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> res = new ArrayList<>();
        if(pRoot==null)
            return res;
        LinkedList<TreeNode> ll = new LinkedList<>();
        ll.add(pRoot);
        int count=1, temp;
        TreeNode curr;
        while(!ll.isEmpty()){
            //initialize
            temp = count;
            count = 0;
            res.add(new ArrayList<Integer>());
            //处理当前层
            while(temp>0){
                curr = ll.poll();
                temp--;
                res.get(res.size()-1).add(curr.val);
                if(curr.left!=null){
                    ll.add(curr.left);
                    count++;
                }
                if(curr.right != null){
                    ll.add(curr.right);
                    count++;
                }
            }
        }
        return res;
    }
}
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;

public class Solution {
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        //execute
        ArrayList<Integer> al = new ArrayList<Integer>();
        if(root == null) // input check
            return al;
        Deque<TreeNode> d = new LinkedList<TreeNode>();
        int toBePrinted, nextLevel = 0;
        TreeNode curr = null;
        d.addLast(root);
        toBePrinted++;
        while(!d.isEmpty()){
            curr = d.pollFirst(); 
            al.add(curr.val);
            toBePrinted--;
            if(curr.left != null)//不要忘记队列中添加null{
                d.addLast(curr.left);
                nextLevel++;
            if(curr.right != null){
                d.addLast(curr.right);
                nextLevel++;
            }
            if(toBePrinted==0){ // 当toBePrinted为0时, 下一轮循环就要打印下一层了, 所以更新toBePrinted的值并将nextLevel置零
                toBePrinted = nextLevel;
                nextLevel = 0;
                al.add(99999) // 暂时用99999表示换行
            }
        }
        }
        return al;
    }

题目三

之字形打印二叉树
请事先一个函数按照之字形顺序打印二叉树, 即第一行按照从左到右的顺序打印, 第二层按照从右到左的顺序打印, 第三层再按照从左到右地顺序打印, 其他行以此类推

思路

  • 使用两个栈实现之字形打印
  • 打印奇数层的节点时,将该层节点的子节点(如果有的话)从左向右地压入栈s1
  • 打印偶数层的节点时,将该层节点的子节点(如果有的话)从右向左地压入栈s2
  • 创建一个变量OddOrEven表示当前层是奇数层还是偶数层
  • 当s1或者s2为空时, 改变OddOrEven的奇偶性
  • 直到s1和s2都为空时, 跳出循环, 终止打印
 //bfs
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> list = new ArrayList<>();
        if(root==null){
            return list;
        }
        Deque<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        boolean odd = true;
        while(!queue.isEmpty()){
            int count = queue.size();
            List<Integer> al = new ArrayList<>();
            if(odd){
                for(int i=0; i<count; i++){
                    TreeNode cur = queue.pollLast();
                    al.add(cur.val);
                    if(cur.left!=null){
                        queue.addFirst(cur.left);
                    }
                    if(cur.right!=null){
                        queue.addFirst(cur.right);
                    }
                }               
            }else{
                for(int i=0; i<count; i++){
                    TreeNode cur = queue.pollFirst();
                    al.add(cur.val);
                    if(cur.right!=null){
                        queue.addLast(cur.right);
                    }
                    if(cur.left!=null){
                        queue.addLast(cur.left);
                    }
                }
            }
            odd = !odd;
            list.add(al);
        }
        return list;
    }
}
import java.util.ArrayList;
import java.util.Stack;
public class Solution {
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        //execute
        ArrayList<Integer> al = new ArrayList<Integer>();
        if(root == null) // input check
            return al;
        Stack<Integer> s1 = new Stack<Integer>();
        Stack<Integer> s2 = new Stack<Integer>();
        int toBePrinted, nextLevel = 0;
        TreeNode curr = null;
        s1.addLast(root);
        // 从上到下, 奇数层:从左到右打印; 偶数层:从右到左打印
        // 通过两个Stack实现
        int OddOrEven = 1; // 1代表奇数层, 0代表偶数层
        
        while(!s1.isEmpty() || !s2.isEmpty()){
            if(OddOrEven == 1){ // 当前是第奇数层. 当前层的子节点先左后右地压入栈中
                curr = s1.pop();
                al.addLast(curr.val);
                if(curr.left != null)
                    s2.push(curr.left);
                if(curr.right != null)
                    s2.push(curr.right);
            }
            else{ // 当前是第偶数层. 当前层的子节点先右后左地压入栈中
                curr = s2.pop();
                al.addLast(curr.val);
                if(curr.right != null)
                    s1.push(curr.right);
                if(curr.left != null)
                    s1.push(curr.left);
            }
            if(s1.isEmpty() || s2.isEmpty()){ //未验证该代码的鲁棒性
                // 奇偶转换
                OddOrEven = 1 - OddOrEven;
            }
        }
    }
        return al;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值