代码随想录二叉树——二叉树的层序遍历

题目

给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
代码随想录二叉树——二叉树的层序遍历_第1张图片

思路

层序遍历——>BFS队列

下面对二叉树进行DFS遍历和BFS遍历的代码进行比较:

DFS遍历,使用递归

void dfs(TreeNode root) {
    if (root == null) {
        return;
    }
    dfs(root.left);
    dfs(root.right);
}

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);
        }
    }
}

从代码直观来看,DFS的代码比BFS简洁太多,因为递归的方式是隐含的使用了系统的栈,不需要我们自己手动去维护一个数据结构;而BFS需要手动维护队列。

如果只是简单地将二叉树遍历一遍,那么 DFS 显然是更方便的选择,但是如果考虑层序遍历,那么BFS是优先选择。

BFS主要用于:层序遍历最短路径,而且「BFS 遍历」、「层序遍历」、「最短路径」实际上是递进的关系。在 BFS 遍历的基础上区分遍历的每一层,就得到了层序遍历。在层序遍历的基础上记录层数,就得到了最短路径。

对于层序遍历,使用BFS的顺序是一致的,但是最终结果有所区别,要考虑以下问题:

  • 层序遍历要求区分每一层,也就是返回一个二维数组。
  • 而BFS 的遍历结果是一个一维数组,无法区分每一层。

代码随想录二叉树——二叉树的层序遍历_第2张图片
所以需要修改一下代码,在每一层遍历开始前,先记录队列中的结点数量 n(也就是这一层的结点数量),然后一口气处理完这一层的 n 个结点。比如队里中有2,3,那么 n = 2,先考虑2,把2的左右孩子加入队列,2出队列;再考虑3,把3的左右孩子加入队列,3出队列,然后进入到下一层,记录下一层将诶点数量,n = 4,以此类推…

class Solution {
	//BFS:借助队列
	public List<List<Integer>> levelOrder(TreeNode root){
		List<List<Integer>> res = new ArrayList<List<Integer>>();//记录最终结果
		Queue<TreeNode> queue = new LinkedList<>();//负责遍历二叉树,其中Queue是一个接口,不能实例化,只能创建实现了这个接口的实现类对象
		
		if (root != null) {
			queue.add(root);//根节点入队
		}

		while(!queue.isEmpty()){
			List<Integer> level = new ArrayList<>();//level记录每一层的节点数,如[1],[2,3],[4,5,6],多个level组成最终的res
			int n = queue.size();//记录当前层节点个数(因为队列中始终维护一层的元素),控制队列弹出节点数量,如第一层一个元素则队列出一个元素,第二层两个元素,则队列出两个元素
			
			//这里要注意,java 中 while(n--)是会报错的,或者直接用for循环:for (int i = 0; i < n; i++),这里的i无实际意义,只是为了循环n次
			//要么用while()一定要加上判断while(n-- > 0)
			while(n-- > 0){//控制队列出元素的个数,如第二层元素个数为2则队列弹出两个元素,保证处理完当前层再去遍历下一层
				TreeNode node = queue.poll();//poll返回队首元素
				level.add(node.val);//放到一维数组中
				if(node.left != null) queue.add(node.left);//如果左孩子不为空,则加入队列
				if(node.right != null) queue.add(node.right);//如果右孩子不为空,则加入队列
			}
			res.add(level);//将多个一维数组放到二维数组中
		}
		return res;
	}
} 

层序遍历模板:

class Solution {
	public int[] levelOrder(TreeNode root){//返回值根据题目而定,可以是int[],也可以是List等等
		List<Integer> res = new ArrayList<>();
		Queue<TreeNode> queue = new LinkedList<>();//负责遍历二叉树
		if (root != null) {
			queue.add(root);
		}
		while(!queue.isEmpty()){
			TreeNode node = queue.poll();
			res.add(node.val);
			if(node.left != null) queue.add(node.left);
			if(node.right != null) queue.add(node.right);
		}
        int n = res.size();
        int[] ans = new int[n];
        for(int i = 0; i < n; i++ ){
            ans[i] = res.get(i);
        }
		return ans;
	}
} 

你可能感兴趣的:(代码随想录,java,开发语言)