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;
}