代码随想录刷题----二叉树层序遍历
二叉树层序遍历思想比较简单:先借助队列逐层存入根节点,再在出队时逐层将节点存入队列直到遍历完成。
102.二叉树的层序遍历
是最基础的层序遍历题。仅需注意在出队前记录当前队列中节点个数,以免新入队的子节点被处理。
//102.二叉树层序遍历
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
//根为空则直接返回
if(root == null) {
return res;
}
Queue<TreeNode> q= new LinkedList<>();
q.offer(root);
while(q.size() > 0) {
int num = q.size(); //记录当前层节点数量防止新入队节点出队
List<Integer> list = new ArrayList<>();
for(int i = 0; i < num; i++) {
TreeNode node = q.poll();
if(node.left != null) {
q.offer(node.left);
}
if(node.right != null) {
q.offer(node.right);
}
list.add(node.val);
}
res.add(list);
}
return res;
}
}
107.二叉树的层序遍历II
与上一题类似,仅需在返回前将队列反转即可
199.二叉树的右视图
仅需在层序遍历的基础上记录每轮循环中队列里的最后一个节点即可
class Solution {
public List<Integer> rightSideView(TreeNode root) {
List<Integer>res = new ArrayList<>();
if(root == null) {
return res;
}
LinkedList<TreeNode> q = new LinkedList<>();
q.add(root);
while(q.size() > 0) {
res.add(q.getLast().val);//记录每层队列的最后一个元素即为该层的右视元素
int num = q.size();
for(int i = 0; i < num; i++) {
TreeNode node = q.removeFirst();
if(node.left != null) {
q.add(node.left);
}
if(node.right != null) {
q.add(node.right);
}
}
}
return res;
}
}
637.二叉树的层平均值
本题仅需在层序遍历出队的过程中记录每层的节点个数以及节点数字和即可
class Solution {
public List<Double> averageOfLevels(TreeNode root) {
List<Double> res = new ArrayList<>();
if(root == null) {
return res;
}
LinkedList<TreeNode> q = new LinkedList<>();
q.add(root);
while(q.size() > 0) {
int num = q.size();
double sum = 0;
int n = 0;
for(int i = 0; i < num; i++) {
TreeNode node = q.removeFirst();
//记录节点个数和每层节点的数字和
sum += node.val;
n++;
if(node.left != null) {
q.add(node.left);
}
if(node.right != null) {
q.add(node.right);
}
}
res.add(sum/n);
}
return res;
}
}
429.N叉树的层序遍历
N叉树与二叉树类似,本题定义的N叉树孩子节点为一个队列,仅需在二叉树遍历基础上将对左孩子右孩子的判断换成对子节点的判断即可。
/*
// Definition for a Node.
class Node {
public int val;
public List<Node> children;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val, List<Node> _children) {
val = _val;
children = _children;
}
};
*/
class Solution {
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> res = new ArrayList<>();
if(root == null) {
return res;
}
LinkedList<Node> q = new LinkedList<>();
q.add(root);
while(q.size() > 0) {
List<Integer> list = new ArrayList<>();
int num = q.size();
for(int i = 0; i < num; i++) {
Node node = q.removeFirst();
//判断是否有孩子节点,有则全部入队
if(node.children != null) {
q.addAll(node.children);
}
list.add(node.val);
}
res.add(list);
}
return res;
}
}
515.在每个树行中找最大值
在遍历出队时比较节点大小找出最大值
class Solution {
public List<Integer> largestValues(TreeNode root) {
List<Integer> res = new ArrayList<>();
if(root == null) {
return res;
}
LinkedList<TreeNode> q = new LinkedList<>();
q.add(root);
while(q.size() > 0) {
int num = q.size();
int max = Integer.MIN_VALUE;
for(int i = 0; i < num; i++) {
TreeNode node = q.removeFirst();
//出队时找出最大值
if(node.val > max) {
max = node.val;
}
if(node.left != null) {
q.add(node.left);
}
if(node.right != null) {
q.add(node.right);
}
}
res.add(max);
}
return res;
}
}
116.填充每个节点的下一个右侧节点指针
本题给每个节点增加了一个next指针用以指向右侧的节点,若该节点右侧没有节点则指向null。在思路上我们希望从右向左先出队,这样就可以使用一个next变量记录下右侧节点,当左侧的节点出队时将next指针指向保存的右侧节点即可。要使右侧节点先出队只需要先让它入队即可。
class Solution {
public Node connect(Node root) {
if(root == null) {
return null;
}
LinkedList<Node> q = new LinkedList<>();
q.add(root);
while(q.size() > 0) {
//最右侧节点的next指针指向null
Node next = null;
int num = q.size();
for(int i = 0; i < num; i++) {
Node node = q.removeFirst();
//右侧节点先入队,保证出队顺序为从右到左
if(node.right != null) {
q.add(node.right);
}
if(node.left != null) {
q.add(node.left);
}
//将当前节点的next指针指向右侧节点
node.next = next;
//保存当前节点
next = node;
}
}
return root;
}
}
117. 填充每个节点的下一个右侧节点指针 II
这题与前一题的不同之处是前一题为完全二叉树而本题没有这个条件,但思路和代码都是一模一样的
104.二叉树的最大深度
看到这题最先想到的是二叉树的深度优先遍历,但实际上二叉树的深度即为他的层数,因此用层序遍历可以很方便的计算出深度
class Solution {
public int maxDepth(TreeNode root) {
int height = 0;
if(root == null) {
return 0;
}
LinkedList<TreeNode> q = new LinkedList<>();
q.add(root);
while(q.size() > 0) {
int num = q.size();
for(int i = 0; i < num; i++) {
TreeNode node = q.removeFirst();
if(node.left != null) {
q.add(node.left);
}
if(node.right != null) {
q.add(node.right);
}
}
//记录层数
height++;
}
return height;
}
}
111.二叉树的最小深度
与上题同理,最小深度即为第一个没有左右孩子节点的节点所在的层数,仅需在出队时判断是否有左右孩子即可
class Solution {
public int minDepth(TreeNode root) {
int height = 0;
if(root == null) {
return 0;
}
LinkedList<TreeNode> q = new LinkedList<>();
q.add(root);
while(q.size() > 0) {
int num = q.size();
for(int i = 0; i < num; i++) {
TreeNode node = q.removeFirst();
if(node.left != null) {
q.add(node.left);
}
if(node.right != null) {
q.add(node.right);
}
//没有左右孩子则表示该层为最小深度
if(node.left == null&&node.right == null) {
//加上本层的高度
return height+1;
}
}
height++;
}
return height;
}
}
总结
层序遍历的题目都大同小异,只需要记住基本的遍历思想,在实际问题中稍加改变即可解决问题。