剑指 Offer 32 - I. 从上到下打印二叉树
从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。
例如:
给定二叉树: [3,9,20,null,null,15,7]
,
3 / \ 9 20 / \ 15 7
返回:
[3,9,20,15,7]
这道题就是最基础的层序遍历,层序遍历就是,广度优先遍历,一层一层的打印。
如何做到层序遍历呢?
我们肯定需要一个指针来按照层序遍历的顺序去移动。
所以我们想到要用队列,按照:每个节点入队列、左孩子入队列、右孩子入队列 这样的顺序,然后每一轮出队列就行。
具体动态图请参考:剑指 Offer 32 - I. 从上到下打印二叉树
代码思路
1.将树的根节点加入到对列
2.开始循环:指针指向队列的头,出队列、左孩子入队列、右孩子入队列
我认为最关键的一点就是 通过每次入队列出队列,来让指针指向队列头元素,这样指针就能按照层序遍历的顺序来指向
class Solution {
public int[] levelOrder(TreeNode root) {
if(root == null) return new int[0];
Queue queue = new LinkedList<>();
queue.add(root);
ArrayList arrayList = new ArrayList<>();
while (!queue.isEmpty()){
TreeNode node = queue.poll();
arrayList.add( node.val );
if (node.left!=null)queue.add(node.left);
if (node.right!=null)queue.add(node.right);
}
int[] res = new int[arrayList.size()];
for(int i = 0; i < arrayList.size(); i++)
res[i] = arrayList.get(i);
return res;
}
}
剑指 Offer 32 - II. 从上到下打印二叉树 II - 力扣(LeetCode)
从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
例如:
给定二叉树: [3,9,20,null,null,15,7]
,
3 / \ 9 20 / \ 15 7
返回其层次遍历结果:
[ [3], [9,20], [15,7] ]
上道题的返回结果是
[3,9,20,15,7]
这道题的返回结果是集合嵌套集合
[ [3], [9,20], [15,7] ]
上道题是将层序遍历的结果放到数组中,这道题其实比上到题难。
上道题,你只需要把每个节点按照层序遍历走一遍就行了,不需要知道哪里具体是分层了,但是这道题要多一个操作,那就是多一个分层的操作。
怎么判断什么时候分层?
起初我想的是,按照树的每层的大小来分层,例如第一层的大小是1,第二层的大小是2,第三层是4,第四层是8,那以此类推,每次记录一个大小,遍历到这个大小的时候就分层。
但是问题是,这不是满二叉树,除了第一层,其他层的大小都是不一定的。
看了题解的代码,恍然大悟。
和上道题一样,先用队列去遍历每个节点,然后何时直到一层遍历完了?
那就是当上一层的元素都出队列之后,下一层的元素都进入队列了,那么这个时候,下一层的大小就是当前队列的大小。
第一层的大小我们知道,它一定是1,那么之后的每层的大小我们都不知道,但是我们可以去算一下,当第一层元素都出队列的时候,第二层都进入队列了,所以当前队列的大小就是第二层的元素的大小。
也就是在第一题层序遍历的基础上加一个for循环判断
for (int size = queue.size(); size > 0 ; size--) {
TreeNode node = queue.poll();
rowList.add(node.val);
if (node.left!=null)queue.add(node.left);
if (node.right!=null)queue.add(node.right);
}
例如下面这个例子
3 / \ 9 20 / \ 15 7
初始化的时候,3先进入队列。
开始循环:
第一层大小是1,循环1次:3出队列,3的左右孩子进入队列,队列的大小是2
第二层大小是2,循环2次:9出队列 ,9没有左右孩子
20出队列,20的左右孩子入队列,这时候循环2次完毕,队列大小是2,所以下一层的大小是2
第三层大小是2,循环2次:15出队列,15没有左右孩子
7出队类,7没有左右孩子,这时候循环两次结束,队列大小是0,结束循环。
class Solution {
public List> levelOrder(TreeNode root) {
if (root == null)return new LinkedList<>();
List> res = new LinkedList<>();
Queue queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()){
List rowList = new LinkedList<>();
for (int size = queue.size(); size > 0 ; size--) {
TreeNode node = queue.poll();
rowList.add(node.val);
if (node.left!=null)queue.add(node.left);
if (node.right!=null)queue.add(node.right);
}
res.add(rowList);
}
return res ;
}
}
剑指 Offer 32 - III. 从上到下打印二叉树 III - 力扣(LeetCode)
请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。
例如:
给定二叉树: [3,9,20,null,null,15,7]
,
3 / \ 9 20 / \ 15 7
返回其层次遍历结果:
[ [3], [20,9], [15,7] ]
这道题就是在第二题的基础上加了一个,奇数层的时候打印顺序不变,偶数层的时候,打印顺序相反。
所以,第二题搞懂了的话,第三题直接就多一个判断奇偶,然后翻转一下list就行了
class Solution {
public List> levelOrder(TreeNode root) {
if (root == null)return new LinkedList<>();
Queue queue = new LinkedList();
List> res = new LinkedList<>();
queue.add(root);
int turn = 0;
while (!queue.isEmpty()){
turn++;
List list = new LinkedList<>();
for (int size = queue.size();size>0 ; size--) {
TreeNode current = queue.poll();
list.add(current.val);
if (current.left != null)queue.add(current.left);
if (current.right != null)queue.add(current.right);
}
if (turn % 2 == 0){ //偶数:从右到左
//翻转list
List list2 = new LinkedList();
for (int i = list.size()-1;i >= 0 ; i--) {
list2.add(list.get(i));
}
res.add(list2);
}else { //奇数:从左到右
res.add(list);
}
}
return res;
}
}