队列元素从队尾进,从队头出
树形bfs:
核心:
step1:将队头节点移出队列
step2:然后将这个结点的左右孩子结点加入队列
Queue queue = new LinkedList();
//先将根节点加入队列
queue.add(root);
//只要队列里还存在元素
while(queue.size()!=0)
{
//求出队列中此时有几个元素,这些元素都要出队列,而且出队列后要把它们的左右孩子都加入队列
int size=queue.size();
for(int i=0;i<size;i++)
{
Node current=queue.remove();//将队头结点移出队列
//将刚刚移出队列的结点的左右孩子结点加入队列
if(current.left!=null)
{
queue.add(current.left);
}
if(current.right!=null)
{
queue.add(current.right);
}
}
}
每一轮size是多少,就说明这一层有多少个结点
102
非递归解法:
(1) 这里有个核心:每一轮开始的时候(把上一轮的节点全部出队列之后)都会计算此时队列的长度,此时队列的长度就是二叉树某一层的节点个数,将这一层的节点值全部添加到临时arraylist中,然后开始下一轮(也就是下一层)
也就是说这就是在遍历每一层
(2)每次出队列1个结点,就把这个结点的左右孩子都入队列,每一轮将一层结点出队列
class Node
{
int val;
Node left;
Node right;
public Node(int val)
{
this.val=val;
}
}
class Solution
{
//传入根节点
public static ArrayList levelOrderTraverse(Node root)
{
//最后的结果数组是“数组的数组”形式
//比如:[[1],[2,3],[4,5,6,7]]
ArrayList result=new ArrayList();
if(root==null)
{
return result;
}
//创建队列,队列里装的是结点
Queue queue=new LinkedList();
//将根节点入队列,此时root就是队头结点
queue.offer(root);
//只要队列不为空,就一直循环(开始时队列中有头结点这一个数,队列不为空,进入循环)
while(queue.isEmpty()==false)
{
//统计出此时队列的长度,此时队列的长度是多少,就说明这一层有几个结点,这句话非常非常非常关键
int size=queue.size();
//每一层的节点的值用一个数组来装,装完一层就把这个数组添加到结果数组中
//注意里面装的是结点的值,不是结点
ArrayList temp=new ArrayList();
//每一轮把一层的结点全部弹出队列,并且把这一层结点的左右孩子结点全部加进队列
for(int i=0;i<size;i++)
{
//queue.poll()方法表示返回队头元素,并且在队列中删除
// 所以这里会把队头结点删除并且赋给current
Node current=(Node)queue.poll();
//将刚刚删除的队头结点的值添加到temp数组中
temp.add(current.val);
if(current.left!=null)
{
queue.add(current.left);
}
if(current.right!=null)
{
queue.add(current.right);
}
}
result.add(temp);
}
return result;
}
}
public class test
{
public static void main(String[] args) {
Node root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.right.right = new Node(8);
Solution solution = new Solution();
ArrayList a = solution.levelOrderTraverse(root);
System.out.println(a);
//[[1], [2, 3], [4, 8]]
}
}
核心代码就是这一段:核心就是需要将每一个移出队列的结点的左右孩子结点加入队列
Queue queue = new LinkedList();
//先将根节点加入队列
queue.add(root);
//只要队列里还存在元素
while(queue.isEmpty()==false)
{
//求出队列中此时有几个元素,这些元素都要出队列,而且出队列后要把它们的左右孩子都加入队列
int size=queue.size();
for(int i=0;i<size;i++)
{
Node current=queue.remove();//将队头结点移出队列
//将刚刚移出队列的结点的左右孩子结点加入队列
if(current.left!=null)
{
queue.add(current.left);
}
if(current.right!=null)
{
queue.add(current.right);
}
}
}
如果是429. N 叉树的层序遍历 - 力扣(LeetCode)
只需将核心代码改成:
Node current=(Node)queue.poll();
//将刚刚删除的队头结点的值添加到temp数组中
temp.add(current.val);
for(Node child:node.children)
{
if(child!=null)
{
queue.add(child);
}
}
也就是说将队列中一个节点出队列后,不是将这个节点的左右孩子节点入队,而是需要将这个节点的所有孩子节点都入队
class Solution
{
public List<List<Integer>> levelOrder(Node root)
{
ArrayList result=new ArrayList();
if(root==null)
{
return result;
}
Queue<Node> queue=new LinkedList();
queue.offer(root);
//队列不为空,就要继续
while(queue.isEmpty()==false)
{
int size=queue.size();
ArrayList temp=new ArrayList();
for(int i=0;i<size;i++)
{
Node current=queue.poll();
temp.add(current.val);
for(Node child:current.children)
{
if(child!=null)
{
queue.add(child);
}
}
}
result.add(temp);
}
return result;
}
}
107. 二叉树的层序遍历 II - 力扣(LeetCode)
只需将二叉树层序遍历的得到的数组进行反转即可
即多加上这句代码就可以了:
Collections.reverse(result);
class Solution
{
public List<List<Integer>> levelOrderBottom(TreeNode root)
{
List<List<Integer>> result=new ArrayList();
if(root==null)
{
return result;
}
Queue<TreeNode> queue=new LinkedList();
queue.offer(root);
//队列不为空,就要继续
while(queue.isEmpty()==false)
{
int size=queue.size();
List<Integer> temp=new ArrayList();
for(int i=0;i<size;i++)
{
TreeNode current=queue.poll();
temp.add(current.val);
if(current.left!=null)
{
queue.add(current.left);
}
if(current.right!=null)
{
queue.add(current.right);
}
}
result.add(temp);
}
Collections.reverse(result);
return result;
}
}
其实就是把每一层的最后一个元素加入到列表中返回
class Solution
{
public List<Integer> rightSideView(TreeNode root)
{
List<Integer> result=new ArrayList();
if(root==null)
{
return result;
}
Queue<TreeNode> queue=new LinkedList();
queue.offer(root);
//队列不为空,就要继续
while(queue.isEmpty()==false)
{
int size=queue.size();
for(int i=0;i<size;i++)
{
TreeNode current=queue.poll();
if(i==size-1)
{
result.add(current.val);
}
if(current.left!=null)
{
queue.add(current.left);
}
if(current.right!=null)
{
queue.add(current.right);
}
}
}
return result;
}
}
515. 在每个树行中找最大值 - 力扣(LeetCode)
class Solution
{
public List<Integer> largestValues(TreeNode root)
{
List<Integer> result=new ArrayList();
if(root==null)
{
return result;
}
Queue<TreeNode> queue=new LinkedList();
queue.offer(root);
//每一轮负责找出一层的二叉树的节点
while(queue.isEmpty()==false)
{
int size=queue.size();
int temp=Integer.MIN_VALUE;
for(int i=0;i<size;i++)
{
TreeNode current=queue.poll();
if(current.val>temp)
{
temp=current.val;
}
if(current.left!=null)
{
queue.add(current.left);
}
if(current.right!=null)
{
queue.add(current.right);
}
}
result.add(temp);
}
return result;
}
}
class Solution
{
public List<Double> averageOfLevels(TreeNode root)
{
List result=new ArrayList();
if(root==null)
{
return result;
}
Queue<TreeNode> queue=new LinkedList();
queue.offer(root);
//每一轮负责找出一层的二叉树的节点
while(queue.isEmpty()==false)
{
int size=queue.size();
double temp=0;
for(int i=0;i<size;i++)
{
TreeNode current=queue.poll();
temp=temp+current.val;
if(current.left!=null)
{
queue.add(current.left);
}
if(current.right!=null)
{
queue.add(current.right);
}
}
temp=temp/size;
result.add(temp);
}
return result;
}
}
117. 填充每个节点的下一个右侧节点指针 II - 力扣(LeetCode)
class Solution
{
public Node connect(Node root)
{
List result=new ArrayList();
if(root==null)
{
return root;
}
Queue<Node> queue=new LinkedList();
queue.offer(root);
//每一轮负责找出一层的二叉树的节点
while(queue.isEmpty()==false)
{
int size=queue.size();
Node dummy=new Node(-1);
for(int i=0;i<size;i++)
{
Node current=queue.poll();
dummy.next=current;
dummy=current;
if(current.left!=null)
{
queue.add(current.left);
}
if(current.right!=null)
{
queue.add(current.right);
}
}
}
return root;
}
}
力扣103 二叉树的锯齿形层次遍历
就是增加一个标志位flag,flag=1,奇数行,那就不反转列表
flag=0,偶数行,反转列表
class Solution
{
public List<List<Integer>> zigzagLevelOrder(TreeNode root)
{
List<List<Integer>> result=new ArrayList();
if(root==null)
{
return result;
}
Queue<TreeNode> queue=new LinkedList();
queue.offer(root);
int flag=1;
//队列不为空,就要继续
while(queue.isEmpty()==false)
{
int size=queue.size();
List<Integer> temp=new ArrayList();
for(int i=0;i<size;i++)
{
TreeNode current=queue.poll();
temp.add(current.val);
if(current.left!=null)
{
queue.add(current.left);
}
if(current.right!=null)
{
queue.add(current.right);
}
}
if(flag<0) Collections.reverse(temp);
flag=-flag;
result.add(temp);
}
return result;
}
}
力扣1161 求出和最大的那一层层号
class Solution
{
public int maxLevelSum(TreeNode root)
{
int num=1;//统计当前到了第几层
int result=1;
int sum=Integer.MIN_VALUE;//预防每个节点值都是负数情况
Queue<TreeNode> queue=new LinkedList();
queue.offer(root);
//每一轮负责找出一层的二叉树的节点
while(queue.isEmpty()==false)
{
int size=queue.size();
int temp=0;
for(int i=0;i<size;i++)
{
TreeNode current=queue.poll();
temp=temp+current.val;
if(current.left!=null)
{
queue.add(current.left);
}
if(current.right!=null)
{
queue.add(current.right);
}
}
if(temp>sum)
{
sum=temp;
result=num;
}
num++;//nums用来记录层数,表示到了第几层
}
return result;
}
}
力扣513 找树左下角的值(二叉树最底层最左边的值)
class Solution
{
public int findBottomLeftValue(TreeNode root)
{
ArrayList<ArrayList<Integer>> result=new ArrayList();
Queue queue=new LinkedList();
queue.offer(root);
while(queue.isEmpty()==false)
{
int size=queue.size();
ArrayList temp=new ArrayList();
for(int i=0;i<size;i++)
{
TreeNode current=(TreeNode)queue.poll();
temp.add(current.val);
if(current.left!=null)
{
queue.add(current.left);
}
if(current.right!=null)
{
queue.add(current.right);
}
}
result.add(temp);
}
return result.get(result.size()-1).get(0);
}
}
力扣1302 层数最深叶子节点的和
class Solution
{
public int deepestLeavesSum(TreeNode root)
{
ArrayList<ArrayList<Integer>> result=new ArrayList();
Queue queue=new LinkedList();
queue.offer(root);
while(queue.isEmpty()==false)
{
int size=queue.size();
ArrayList temp=new ArrayList();
for(int i=0;i<size;i++)
{
TreeNode current=(TreeNode)queue.poll();
temp.add(current.val);
if(current.left!=null)
{
queue.add(current.left);
}
if(current.right!=null)
{
queue.add(current.right);
}
}
result.add(temp);
}
int num=0;
for(int i=0;i<result.get(result.size()-1).size();i++)
{
num=num+ result.get(result.size()-1).get(i);
}
return num;
}
}
图bfs:
存储图的两种方式:邻接矩阵和邻接表
力扣 542 01矩阵