算法原理
队列基本知识
1.是一个接口底层是通过链表实现的
只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表(从队尾进,从对头处)
2.常见的方法
boolean offer(E e)入队列
E poll() 出队列
peek()获取对头元素
int size()有效元素个数
boolean isEmpty()判读是否为空
搜索类算法
深搜(dfs)vs宽搜(bfs)
宽搜是广度优先遍历 深搜是深度优先遍历(我们在图的数据结构中了解过)
这篇文章主要是利用队列先进先出的特性结合搜索类算法中比较重要的宽搜(bfs)来解决树相关的问题
题目解析
1.N 叉树的层序遍历
题目描述
给定一个N叉树,返回其节点值的层序遍历(即从左到右,逐层遍历)
树的序列化输入时用层序遍历,每个子节点都由null值分割

算法原理
解法:利用队列实现bfs
queue:当队列不空时,拿出队头元素,把队头孩子入队
那么我们如何判断元素在一层? 只需要在入队之前,先统计队列中的元素个数,出队列时只要出相应的个数即可

代码实现
java
class Solution {
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> ret=new ArrayList<>();
if(root==null) return ret;
Queue<Node> q=new LinkedList<>();
q.add(root);
while(!q.isEmpty()){
int sz=q.size();
List<Integer> tmp=new ArrayList<>();
for(int i=0;i<sz;i++){
Node t=q.poll();
for(Node child:t.children){
q.add(child);
}
tmp.add(t.val);
}
ret.add(tmp);
}
return ret;
}
}
2.二叉树的锯齿形层序遍历
题目描述
给你二叉树的根节点root,返回其根节点值的锯齿形层序遍历(即先从左往右,再从右向左,以此类推,层与层之间交替进行)

算法原理
解法:利用队列先进先出的特价来完成层序遍历(和上一道题类似,我们只需要增加一个标记位,让偶数行的信心逆序即可 用boolean/int都可以)

代码实现
java
class Solution {
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> ret=new ArrayList<>();
if(root==null) return ret;
Queue<TreeNode> q=new LinkedList<>();
q.add(root);
int s=1;
while(!q.isEmpty()){
int sz=q.size();
List<Integer> tmp=new ArrayList<>();
for(int i=0;i<sz;i++){
TreeNode t=q.poll();
tmp.add(t.val);
if(t.left!=null){
q.add(t.left);
}
if(t.right!=null){
q.add(t.right);
}
}
if(s%2==0){
Collections.reverse(tmp);
}
ret.add(tmp);
s++;
}
return ret;
}
}
3.二叉树最大宽度
题目描述
给你一颗二叉树的根节点root,返回数的最大宽度
树的最大宽度是所有层中最大的宽度
每一层的宽度被定义为该层最左和最右的非空节点(即两个端点)之间的长度,将这个二叉树视作与满二叉树结构相同,两端点之间会出现一些延伸到这一层的null节点,这些null节点也计入长度

算法原理
解法一:硬来(这是错误的,因为空间复杂度和时间复杂度都超了)
解法二:利用数组存储二叉树的方式,给节点编号

这里我们可以利用queue<pair<TreeNode,int>> 宽度计算:队头-队尾+1
可以直接搞一个数组来模拟数列
细节:
下标有可能溢出
当我们相减之后,即使溢出,结果也是正确的(但计算本质上是算两者之间的距离,距离是不会溢出的,距离是正确的 题目上说不会超过32位,说明不会超过一圈)
代码实现
java
class Solution {
public int widthOfBinaryTree(TreeNode root) {
List<Pair<TreeNode,Integer>> q=new ArrayList<>();
q.add(new Pair<TreeNode,Integer>(root,1));
int ret=0;
while(!q.isEmpty()){
Pair<TreeNode,Integer> t1=q.get(0);
Pair<TreeNode,Integer> t2=q.get(q.size()-1);
ret=Math.max(ret,t2.getValue()-t1.getValue()+1);
List<Pair<TreeNode,Integer>> tmp=new ArrayList<>();
for(Pair<TreeNode,Integer> t:q){
TreeNode node =t.getKey();
int index=t.getValue();
if(node.left!=null){
tmp.add(new Pair<TreeNode,Integer>(node.left,index*2));
}
if(node.right!=null){
tmp.add(new Pair<TreeNode,Integer>(node.right,index*2+1));
}
}
q=tmp;
}
return ret;
}
}
4.在每个树行中找最大值
题目描述
给定一棵二叉树的根节点root,请找出该二叉树中每一层的最大值
算法原理
利用层序遍历,统计出每一层的最大值
代码实现
java
class Solution {
public List<Integer> largestValues(TreeNode root) {
List<Integer> ret=new ArrayList<>();
if(root==null) return ret;
Queue<TreeNode> q=new LinkedList<>();
q.add(root);
while(!q.isEmpty()){
int sz=q.size();
int tmp=Integer.MIN_VALUE;
for(int i=0;i<sz;i++){
TreeNode t=q.poll();
tmp=Math.max(t.val,tmp);
if(t.left!=null){
q.add(t.left);
}
if(t.right!=null){
q.add(t.right);
}
}
ret.add(tmp);
}
return ret;
}
}