二叉树的广度优先遍历BFS
BFS 遍历使用队列数据结构:
void bfs(TreeNode root) {
Queue<TreeNode> queue = new ArrayDeque<>();
queue.add(root);
while (!queue.isEmpty()) {
TreeNode node = queue.poll(); // Java 的 pop 写作 poll()
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
}
}
层序遍历要求我们区分每一层,也就是返回一个二维数组。而 BFS 的遍历结果是一个一维数组,无法区分每一层。
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res =new ArrayList<>();//题目要求的是一个二维数组
Queue<TreeNode> queue = new ArrayDeque<>();
if(root!=null){
queue.add(root);
}
// while 循环的每一轮中,都是将当前层的所有结点出队列,再将下一层的所有结点入队列
while(!queue.isEmpty()){
int n=queue.size();//记录队列中的节点数量n
List<Integer> level =new ArrayList<>();//记录每一层的节点
for(int i=0;i<n;i++){// 变量 i 无实际意义,只是为了循环 n 次
TreeNode node = queue.poll();
level.add(node.val);//把当前层节点值加入level中
if(node.left!=null){
queue.add(node.left);
}
if(node.right!=null){
queue.add(node.right);
}
}
res.add(level);
}
return res;
}
}
- 思路和上一题一样,最后反转
public List<List<Integer>> levelOrderBottom(TreeNode root) {
List<List<Integer>> res =new ArrayList<>();//题目要求的是一个二维数组
Queue<TreeNode> queue = new ArrayDeque<>();
if(root!=null){
queue.add(root);
}
// while 循环的每一轮中,都是将当前层的所有结点出队列,再将下一层的所有结点入队列
while(!queue.isEmpty()){
int n=queue.size();//记录队列中的节点数量n
List<Integer> level =new ArrayList<>();//记录每一层的节点
for(int i=0;i<n;i++){// 变量 i 无实际意义,只是为了循环 n 次
TreeNode node = queue.poll();
level.add(node.val);//把当前层节点值加入level中
if(node.left!=null){
queue.add(node.left);
}
if(node.right!=null){
queue.add(node.right);
}
}
res.add(level);
}
Collections.reverse(res);//反转
return res;
}
}
- 关键是记录每层最后一个节点
public List<Integer> rightSideView(TreeNode root) {
List<Integer> res =new ArrayList<>();
Queue<TreeNode> queue = new ArrayDeque<>();
if(root!=null){
queue.add(root);
}
// while 循环的每一轮中,都是将当前层的所有结点出队列,再将下一层的所有结点入队列
while(!queue.isEmpty()){
int n=queue.size();//记录队列中的节点数量n
for(int i=0;i<n;i++){// 变量 i 无实际意义,只是为了循环 n 次
TreeNode node = queue.poll();
if(i==n-1){//遍历到当前层最后一个节点时,把节点值加入res
res.add(node.val);
}
if(node.left!=null){
queue.add(node.left);
}
if(node.right!=null){
queue.add(node.right);
}
}
}
return res;
}
}
public List<Double> averageOfLevels(TreeNode root) {
List<Double> res = new ArrayList<>();
Queue<TreeNode> queue = new ArrayDeque<>();
if(root!=null){
queue.add(root);
}
while(!queue.isEmpty()){
int n=queue.size();
Double s=0.0;//要注意类型,不然最后会报错
for(int i=0;i<n;i++){
TreeNode node = queue.poll();
s+=node.val;
if(node.left!=null){
queue.add(node.left);
}
if(node.right!=null){
queue.add(node.right);
}
}
res.add(s/n);
}
return res;
}
}
- 关键在于遍历children节点
class Solution {
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> res =new ArrayList<>();//题目要求的是一个二维数组
Queue<Node> queue = new ArrayDeque<>();
if(root!=null){
queue.add(root);
}
// while 循环的每一轮中,都是将当前层的所有结点出队列,再将下一层的所有结点入队列
while(!queue.isEmpty()){
int n=queue.size();//记录队列中的节点数量n
List<Integer> level =new ArrayList<>();//记录每一层的节点
for(int i=0;i<n;i++){// 变量 i 无实际意义,只是为了循环 n 次
Node node = queue.poll();
level.add(node.val);//把当前层节点值加入level中
for(Node child:node.children){//遍历node的子节点,加入队列
queue.add(child);
}
}
res.add(level);
}
return res;
}
}
public List<Integer> largestValues(TreeNode root) {
List<Integer> res =new ArrayList<>();
Queue<TreeNode> queue = new ArrayDeque<>();
if(root!=null){
queue.add(root);
}
// while 循环的每一轮中,都是将当前层的所有结点出队列,再将下一层的所有结点入队列
while(!queue.isEmpty()){
int n=queue.size();//记录队列中的节点数量n
List<Integer> level =new ArrayList<>();//记录每一层的节点
for(int i=0;i<n;i++){// 变量 i 无实际意义,只是为了循环 n 次
TreeNode node = queue.poll();
level.add(node.val);//把当前层节点值加入level中
if(node.left!=null){
queue.add(node.left);
}
if(node.right!=null){
queue.add(node.right);
}
}
res.add(Collections.max(level));
}
return res;
}
}
7.116. 填充每个节点的下一个右侧节点指针 8. 117. 填充每个节点的下一个右侧节点指针 II
- 这两题一个是完美二叉树,一个是普通二叉树,解法都一样
public Node connect(Node root) {
if(root==null){
return root;
}
Queue<Node> queue = new ArrayDeque<>();
queue.add(root);
while(!queue.isEmpty()){
int n=queue.size();
for(int i=0;i<n;i++){
Node node=queue.poll();
if(i<n-1){
node.next=queue.peek();
}
if(node.left!=null){
queue.add(node.left);
}
if(node.right!=null){
queue.add(node.right);
}
}
}
return root;
}
}
public int maxDepth(TreeNode root) {
int maxDepth=0;
Queue<TreeNode> queue = new ArrayDeque<>();
if(root!=null){
queue.add(root);
}
// while 循环的每一轮中,都是将当前层的所有结点出队列,再将下一层的所有结点入队列
while(!queue.isEmpty()){
int n=queue.size();//记录队列中的节点数量n
for(int i=0;i<n;i++){// 变量 i 无实际意义,只是为了循环 n 次
TreeNode node = queue.poll();
if(node.left!=null){
queue.add(node.left);
}
if(node.right!=null){
queue.add(node.right);
}
}
maxDepth++;
}
return maxDepth;
}
}
- 返回遇到第一个叶子节点时的深度最快捷
public int minDepth(TreeNode root) {
int minDepth=0;
Queue<TreeNode> queue = new ArrayDeque<>();
if(root!=null){
queue.add(root);
}
// while 循环的每一轮中,都是将当前层的所有结点出队列,再将下一层的所有结点入队列
while(!queue.isEmpty()){
int n=queue.size();//记录队列中的节点数量n
minDepth++;//深度+1
for(int i=0;i<n;i++){// 变量 i 无实际意义,只是为了循环 n 次
TreeNode node = queue.poll();
if(node.left==null&&node.right==null){//遇到第一个叶子节点就返回
return minDepth;
}
if(node.left!=null){
queue.add(node.left);
}
if(node.right!=null){
queue.add(node.right);
}
}
}
return minDepth;
}
}