层序遍历
学会二叉树的层序遍历,可以一口气打完以下十题:
- 102.二叉树的层序遍历
- 107.二叉树的层次遍历II
- 199.二叉树的右视图
- 637.二叉树的层平均值
- 429.N叉树的层序遍历
- 515.在每个树行中找最大值
- 116.填充每个节点的下一个右侧节点指针
- 117.填充每个节点的下一个右侧节点指针II
- 104.二叉树的最大深度
- 111.二叉树的最小深度
我们之前讲过了三篇关于二叉树的深度优先遍历的文章:
接下来我们再来介绍二叉树的另一种遍历方式:层序遍历。
层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。这种遍历的方式和我们之前讲过的都不太一样。
需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,而是用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。
而这种层序遍历方式就是图论中的广度优先遍历,只不过我们应用在二叉树上。
import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Queue; public class BinaryTreeLevelOrderTraversal { public List<List<Integer>> resList = new ArrayList<List<Integer>>();//记录最后二维数组的结果,N层 public List<List<Integer>> levelOrder(TreeNode root){ checkFun02(root); return resList; } //BFS--迭代方式--借助队列 public void checkFun02(TreeNode node){ if(node == null) return; Queue<TreeNode> que = new LinkedList<TreeNode>();//定义队列,队列里放TreeNode //队列不为空 que.offer(node); //开始遍历 while (!que.isEmpty()) {//遍历的终止条件,没有元素在队列中 List<Integer> itemList = new ArrayList<Integer>();//记录一维数组,记录一层的结果 int len = que.size();//记录当前节点数量 while (len > 0){ TreeNode tmpNode = que.poll();//先获取弹出的第一个元素 itemList.add(tmpNode.val);//结果记录在一维数组里 //开始下面一层 if(tmpNode.left !=null)que.offer(tmpNode.left); if(tmpNode.right !=null) que.offer(tmpNode.right); len--; } resList.add(itemList); } } }
面试常见
两两交换的是指针,不是数值
可以发现想要翻转它,其实就把每一个节点的左右孩子交换一下就可以了。
关键在于遍历顺序,前中后序应该选哪一种遍历顺序? (一些同学这道题都过了,但是不知道自己用的是什么顺序)
遍历的过程中去翻转每一个节点的左右孩子就可以达到整体翻转的效果。
注意只要把每一个节点的左右孩子翻转一下,就可以达到整体翻转的效果
这道题目使用前序遍历和后序遍历都可以,唯独中序遍历不方便,因为中序遍历会把某些节点的左右孩子翻转了两次!建议拿纸画一画,就理解了
那么层序遍历可以不可以呢?依然可以的!只要把每一个节点的左右孩子翻转一下的遍历方式都是可以的!
public class InvertBInaryTree { //DFS递归 /** * 前后序遍历都可以 * 中序不行,因为先左孩子交换孩子,再根交换孩子(做完后,右孩子已经变成了原来的左孩子),再右孩子交换孩子(此时其实是对原来的左孩子做交换) */ //1.递归-前序遍历 public TreeNode invertTree(TreeNode root){//1.确定返回值和参数 if(root == null) return null;//2.确定终止条件 //3.处理逻辑:前序遍历-中(处理逻辑)左右 swapChildren(root);//翻转-每一个节点的左右孩子交换一下 invertTree(root.left);//向左遍历 invertTree(root.right);//向右遍历 return root; } private void swapChildren(TreeNode root){ TreeNode temp = root.left; root.left = root.right; root.right = temp; } }
public class SymmetricTree { /** * 递归法-后序 */ public boolean isSymmetric(TreeNode root){ return compare(root.left, root.right); } private boolean compare(TreeNode left, TreeNode right){//递归三部中第一步确认返回值和参数 //第二步确定终止条件 if(left == null && right != null){ return false; } if(left != null && right == null){ return false; } if(left == null && right == null){ return true; } //左右节点值不等 if (left.val != right.val){ return false; } //左右节点不为空且数值相等 //第三部向下遍历-单层递归逻辑 // 比较外节点 boolean compareOUtside = compare(left.left, right.right); // 比较内侧节点 boolean compareInside = compare(left.right, right.left); return compareOUtside && compareInside; } }