二叉树的层序遍历
1.层序遍历
层序遍历一个二叉树。就是从左到右一层一层的区遍历二叉树。为了实现层序遍历,我们需要借助一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,而栈先进后出适合模拟深度优先遍历也就是递归的逻辑。
2.实例
2.1二叉树的层序遍历
思路:
1.创建队列用来存储节点,创建list集合用来存储结果
2.逐层记录结果即可。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> ans = new ArrayList<>();//用来输出结果
Queue<TreeNode> queue = new LinkedList<>();//创建一个队列,用来逐层存放
if(root==null) return ans;
queue.offer(root);
while(!queue.isEmpty()){
List<Integer> list = new ArrayList<>();//用于存放值
int len = queue.size();
for(int i=0;i<len;i++){
TreeNode temp = queue.poll();
list.add(temp.val);//放进list
if(temp.left!=null) queue.offer(temp.left);
if(temp.right!=null) queue.offer(temp.right);
}
ans.add(list);
}
return ans;
}
}
2.2 二叉树的层序遍历 II
思路:
和上题基本一致,只需要在输出结果之前将结果反转即可。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List<Integer>> levelOrderBottom(TreeNode root) {
List<List<Integer>> ans = new ArrayList<>();//用来输出结果
Queue<TreeNode> queue = new LinkedList<>();//创建一个队列,用来逐层存放
if(root==null) return ans;
queue.offer(root);
while(!queue.isEmpty()){
List<Integer> list = new ArrayList<>();//用于存放值
int len = queue.size();
for(int i=0;i<len;i++){
TreeNode temp = queue.poll();
list.add(temp.val);//放进list
if(temp.left!=null) queue.offer(temp.left);
if(temp.right!=null) queue.offer(temp.right);
}
ans.add(list);
}
//将ans反转即可
List<List<Integer>> ans1 = new ArrayList<>();
for(int i=ans.size()-1;i>=0;i--){
ans1.add(ans.get(i));
}
return ans1;
}
}
2.3 二叉树的右视图
和模板思路一致,只不过添加的是队列的最后一个元素
if(i==len-1){//保证当前的最后后子节点
ans.add(temp.val);
}
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<Integer> rightSideView(TreeNode root) {
List<Integer> ans = new ArrayList<>();//用来输出结果
Queue<TreeNode> queue = new LinkedList<>();//队列用来存放节点
if(root==null) return ans;
queue.offer(root);
while(!queue.isEmpty()){
int len = queue.size();
for(int i=0;i<len;i++){
TreeNode temp = queue.poll();
if(i==len-1){//保证当前的最后后子节点
ans.add(temp.val);
}
if(temp.left!=null) queue.offer(temp.left);
if(temp.right!=null) queue.offer(temp.right);
}
}
return ans;
}
}
2.4 二叉树的层平均值
依旧套用模板,只是在记录每一层的值,并输出即可。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<Double> averageOfLevels(TreeNode root) {
List<Double> ans =new ArrayList<>();//用于输出答案
Queue<TreeNode> queue = new LinkedList<>();//用于存放节点
if(root==null) return ans;
queue.offer(root);//将节点存入队列中
while(!queue.isEmpty()){
int len = queue.size();
Double sum = 0.0;
for(int i = 0;i<len;i++){
TreeNode temp = queue.poll();
sum+=temp.val;
if(temp.left!=null) queue.offer(temp.left);
if(temp.right!=null) queue.offer(temp.right);
}
ans.add(sum/len);
}
return ans;
}
}
2.5 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>> ans = new ArrayList<>();//用于输出答案
Queue<Node> queue = new LinkedList<>();//用于存储节点
if(root==null) return ans;
queue.offer(root);//将节点存入队列中
while(!queue.isEmpty()){
int len = queue.size();
List<Integer> list = new ArrayList<>();//记录每层的值
for(int i=0;i<len;i++){
Node temp = queue.poll();
list.add(temp.val);
List<Node> children = temp.children;//记录temp的孩子节点
if(children==null||children.size()==0) continue;
for(Node child:children){
if(child!=null){//如果孩子节点不为空
queue.offer(child);//添加到队列
}
}
}
ans.add(list);
}
return ans;
}
}
2.6在每个树行中找最大值
注意注意Collection.max()这一方法,输出集合中的最大值
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<Integer> largestValues(TreeNode root) {
List<Integer> ans = new ArrayList<>();//用于输出答案
Queue<TreeNode> queue = new LinkedList<>();//用于存放节点
if(root==null) return ans;
queue.offer(root);//存放当前节点
while(!queue.isEmpty()){
int len = queue.size();
List<Integer> list = new ArrayList<>();//用于记录每一层的值
for(int i=0;i<len;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);
}
ans.add(Collections.max(list));//注意Collection.max()
}
return ans;
}
}
2.7二叉树的最大深度
遍历完每一层时深度加一即可。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int maxDepth(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();//存放节点
int depth=0;
if(root==null) return depth;
queue.offer(root);//将节点入队
while(!queue.isEmpty()){
int len = queue.size();
for(int i=0;i<len;i++){
TreeNode temp = queue.poll();
if(temp.left!=null) queue.offer(temp.left);
if(temp.right!=null) queue.offer(temp.right);
}
depth++;//层数加一
}
return depth;
}
}
2.8二叉树的最小深度
只需要找出左右节点都为null的节点,返回当前深度即可。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int minDepth(TreeNode root) {
List<Integer> ans = new ArrayList<>();
Queue<TreeNode> queue = new LinkedList<>();
if(root==null) return 0;
queue.offer(root);//根节点入队
int depth=0;
while(!queue.isEmpty()){
depth++;//每进入一层,depth++
int len = queue.size();
for(int i=0;i<len;i++){
TreeNode temp = queue.poll();
//找到叶子节点
if(temp.left==null&&temp.right==null) return depth;
if(temp.left!=null) queue.offer(temp.left);
if(temp.right!=null) queue.offer(temp.right);
}
}
return depth;
}
}
2.9翻转二叉树
思路:使用层序遍历,然后将该层的左右子树翻转即可。
```java
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
/*
* 层序遍历
*/
public TreeNode invertTree(TreeNode root) {
Queue<TreeNode> queue =new LinkedList<>();
if(root==null) return null;
queue.offer(root);//根节点入队
while(!queue.isEmpty()){
int len = queue.size();
for(int i=0;i<len;i++){
TreeNode temp=queue.poll();//取出当前根节点
swapChild(temp);//交换根节点的左右子节点
//继续收集下一层的节点
if(temp.left!=null) queue.offer(temp.left);
if(temp.right!=null) queue.offer(temp.right);
}
}
return root;
}
//交换根节点的左右子节点
private void swapChild(TreeNode root){
TreeNode temp = root.left;
root.left=root.right;
root.right=temp;
}
}
2.10完全二叉树的节点个数
依旧使用层序遍历,定义一个计数器记录节点个数即可
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int countNodes(TreeNode root) {
if(root==null) return 0;
Queue<TreeNode> queue = new LinkedList<>();//存储节点
int num =0;//记录节点个数
queue.offer(root);
while(!queue.isEmpty()){
int len = queue.size();
for(int i=0;i<len;i++){
TreeNode temp = queue.poll();//出队
num++;
if(temp.left!=null) queue.offer(temp.left);
if(temp.right!=null) queue.offer(temp.right);
}
}
return num;
}
}
2.11左叶子之和
本题依旧可以使用层序遍历,解题的关键是如何找到左叶子节点的
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
if(root==null) return 0;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
int sum=0;
while(!queue.isEmpty()){
TreeNode temp=queue.poll();
//注意左叶子的判断
if(temp.left!=null&&temp.left.left==null&&temp.left.right==null){
sum+=temp.left.val;
}
if(temp.left!=null) queue.offer(temp.left);
if(temp.right!=null) queue.offer(temp.right);
}
return sum;
}
}
2.11找树左下角的值
注意int的使用,只有一个值
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
/**
注意只有一个值,所有用int
*/
public int findBottomLeftValue(TreeNode root) {
int ans=0;
Queue<TreeNode> queue =new LinkedList<>();//放节点
queue.offer(root);
while(!queue.isEmpty()){
int len =queue.size();
for(int i=0;i<len;i++){
TreeNode temp = queue.poll();//取出当前节点
if(i==0) ans = temp.val;
if(temp.left!=null) queue.offer(temp.left);
if(temp.right!=null) queue.offer(temp.right);
}
}
return ans;
}
}