1.题目
剑指 Offer 32 - III. 从上到下打印二叉树 III
请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。
例如:
给定二叉树: [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回其层次遍历结果:
[
[3],
[20,9],
[15,7]
]
提示:
节点总数 <= 1000
2.自我思路及实现
面试题32 - I. 从上到下打印二叉树 主要考察 树的按层打印 ;
面试题32 - II. 从上到下打印二叉树 II 额外要求 每一层打印到一行 ;
本题要求打印顺序交替变化
BFS层序遍历+双端队列
Java使用链表实现双端队列
使用标记flag标记奇偶层,使用双端队列代替普通队列
奇数层:头部先出队列,先左子树入队尾,再右子树入队尾
偶数层:尾部先出队列,先右子树入队头,再左子树入队头
时间N
空间N
/**
* 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>> levelOrder(TreeNode root) {
if(root == null)
return new ArrayList<>();
List<List<Integer>> lists = new ArrayList<>();
LinkedList<TreeNode> cur = new LinkedList<>();
cur.add(root);
boolean flag = true;
while( !cur.isEmpty())
{
List<Integer> list = new ArrayList<>();
for(int i = cur.size(); i > 0; i--)
{
if(flag)
{
TreeNode temp = cur.removeFirst();
list.add(temp.val);
if(temp.left != null)
cur.addLast(temp.left);
if(temp.right != null)
cur.addLast(temp.right);
}
else
{
TreeNode temp = cur.removeLast();
list.add(temp.val);
if(temp.right != null)
cur.addFirst(temp.right);
if(temp.left != null)
cur.addFirst(temp.left);
}
}
flag = flag ? false : true;
lists.add(list);
}
return lists;
}
}
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>> levelOrder(TreeNode root) {
if(root == null)
return new ArrayList<>();
List<List<Integer>> lists = new ArrayList<>();
LinkedList<TreeNode> cur = new LinkedList<>();
cur.add(root);
while( !cur.isEmpty())
{
List<Integer> list = new ArrayList<>();
//奇数层
for(int i = cur.size(); i > 0; i--)
{
TreeNode temp = cur.removeFirst();
list.add(temp.val);
if(temp.left != null)
cur.addLast(temp.left);
if(temp.right != null)
cur.addLast(temp.right);
}
lists.add(list);
if(cur.isEmpty())//当奇数层为最后一层,提前结束循环
break;
//偶数层
list = new ArrayList<>(); //换层,因此层对应动态数组重置
for(int i = cur.size(); i > 0; i--)
{
TreeNode temp = cur.removeLast();
list.add(temp.val);
if(temp.right != null)
cur.addFirst(temp.right);
if(temp.left != null)
cur.addFirst(temp.left);
}
lists.add(list);
}
return lists;
}
}
判断次数多的实现
将每层对应的动态数组转为双端链表,队列仍使用普通队列(上一题解法的小改动)
比上述多了很多判断过程
/**
* 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>> levelOrder(TreeNode root) {
if(root == null)
return new ArrayList<List<Integer>>();
List<List<Integer>> lists = new ArrayList<List<Integer>>();
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty())
{
LinkedList<Integer> list = new LinkedList<>(); //
for(int i = queue.size(); i > 0; i--)
{
TreeNode temp = queue.poll();
if(lists.size() % 2 == 0) //注意此处是二维动态数组的容量,代表层数,为0时代表现在执行的是第一层
list.addLast(temp.val); //
else //
list.addFirst(temp.val); //
if(temp.left != null)
queue.offer(temp.left);
if(temp.right != null)
queue.offer(temp.right);
}
lists.add(list);
}
return lists;
}
}
将从右至左的层倒序排列
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
if(root == null)
return new ArrayList<List<Integer>>();
List<List<Integer>> lists = new ArrayList<List<Integer>>();
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty())
{
List<Integer> list = new ArrayList<>();
for(int i = queue.size(); i > 0; i--)
{
TreeNode temp = queue.poll();
list.add(temp.val);
if(temp.left != null)
queue.offer(temp.left);
if(temp.right != null)
queue.offer(temp.right);
}
if(lists.size() % 2 != 0)
Collections.reverse(list);
lists.add(list);
}
return lists;
}
}
4.相关知识
- Java使用链表实现双端队列
addFirst();addLast();
getFirst();getLast();
removeFirst();removeLast(); - Collections : public static void reverse(List<?> list)