二叉树的层次遍历
思路
队列的特点是元素先进先出,符合一层一层的打印二叉树元素的逻辑,只需用一个变量记录每一层有多少个节点,结合广度优先遍历二叉树就可以实现。
迭代法实现
class Solution {
// 存放结果集
private List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> levelOrder(TreeNode root) {
levelOrderCore(root);
return res;
}
private void levelOrderCore(TreeNode root) {
if (root == null) {
return;
}
// 用队列实现广搜
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
// 记录当前层的节点数量
int len = queue.size();
// 清空temp,为存放下一层节点做准备
List<Integer> temp = new ArrayList<>();
// 将当前层的所有节点取出,放入temp
for (int i = 0; i < len; i ++) {
TreeNode node = queue.poll();
temp.add(node.val);
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
}
// 将temp加入到res中
res.add(temp);
}
}
}
递归法实现
因为需要存放树节点的值和根据一个值来判断是否开始遍历下一层的元素,所以递归函数的参数列表中应该有一个树节点和一个int的值,函数不需要返回数据,只需在递归函数对数据进行处理时,将结果加入到res中,所以返回类型是void。当树节点的值为null时,就终止递归,最后是函数的处理逻辑,在递归函数中实现。
class Solution {
// 存放结果集
private List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> levelOrder(TreeNode root) {
levelOrderCore(root, 0);
return res;
}
private void levelOrderCore(TreeNode root, int deep) {
if (root == null) {
return;
}
// 层数加1
deep ++;
// 如果res.size() < deep,说明res还没有这一层节点,需要创建一个list来存放下一层节点
if (res.size() < deep) {
List<Integer> item = new ArrayList<>();
res.add(item);
}
res.get(deep - 1).add(root.val);
// 递归处理
levelOrderCore(root.left, deep);
levelOrderCore(root.right, deep);
}
}
扩展
199.二叉树的右视图
class Solution {
public List<Integer> res = new ArrayList<>();
public List<Integer> rightSideView(TreeNode root) {
rightSideViewCore(root);
return res;
}
private void rightSideViewCore(TreeNode root) {
if (root == null) {
return;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
int len = queue.size();
for (int i = 0; i < len; i ++) {
TreeNode node = queue.poll();
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
if (i == len - 1) {
res.add(node.val);
}
}
}
}
}
637.二叉树的层平均值
class Solution {
private List<Double> res = new ArrayList<>();
public List<Double> averageOfLevels(TreeNode root) {
averageOfLevelsCore(root);
return res;
}
private void averageOfLevelsCore(TreeNode root) {
if (root == null) {
return;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
int count = queue.size();
// sum用double类型
double sum = 0;
for (int i = 0; i < count; i ++) {
TreeNode node = queue.poll();
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
sum += node.val;
}
res.add(sum / count);
}
}
}
429. N 叉树的层序遍历
class Solution {
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> res = new ArrayList<>();
if (root == null) {
return res;
}
Queue<Node> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
int count = queue.size();
List<Integer> item = new ArrayList<>();
for (int i = 0; i < count; i ++) {
Node node = queue.poll();
for (int j = 0; j < node.children.size(); j ++) {
if (node.children.get(j) != null) {
queue.add(node.children.get(j));
}
}
item.add(node.val);
}
res.add(item);
}
return res;
}
}
515. 在每个树行中找最大值
class Solution {
public List<Integer> largestValues(TreeNode root) {
List<Integer> res = new ArrayList<>();
if (root == null) {
return res;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
int count = queue.size();
int max = Integer.MIN_VALUE;
for (int i = 0; i < count; i ++) {
TreeNode node = queue.poll();
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
max = max > node.val ? max : node.val;
}
res.add(max);
}
return res;
}
}
116. 填充每个节点的下一个右侧节点指针
class Solution {
public Node connect(Node root) {
if (root == null) {
return root;
}
Queue<Node> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
int count = queue.size();
for (int i = 0; i < count; i ++) {
Node node = queue.poll();
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
if (i < count - 1) {
node.next = queue.peek();
} else {
node.next = null;
}
}
}
return root;
}
}
117. 填充每个节点的下一个右侧节点指针 II
class Solution {
public Node connect(Node root) {
if (root == null) {
return root;
}
Node head = new Node(0);
Node headCur = head;
Node cur = root;
while (true) {
while (cur != null) {
// 如果当前节点的左子节点不为空,下一层从左子节点开始
if (cur.left != null) {
// 注意这两步
// 这一步如果是下一层第一次开始连接, headCur和head是指向同一个节点
// 也就是说headCur.next=cur.left其实也让head.next=cur.left
headCur.next = cur.left;
// 这一步让headCur向后移动一步
//就是说在下一层连接没完成前,head一直指向下一层的头节点
headCur = headCur.next;
}
// 如果当前节点的右子节点不为空,下一层从右子节点开始
if (cur.right != null) {
headCur.next = cur.right;
headCur = headCur.next;
}
cur = cur.next;
}
// 开始遍历下一层
cur = head.next;
head.next = null;
headCur = head;
// 所有节点处理完了,结束循环
if (cur == null) {
break;
}
}
return root;
}
}