[Java恶补day47] 整理模板·考点十【二叉树层序遍历】
考点十【二叉树层序遍历】
【考点总结】
- Java让Boolean变量逻辑取反:
!
运算符 - Java让ArrayList翻转:
Collections.reverse()
- 计算二叉树最大深度,也可用层序遍历实现
- 比较层序遍历、递归:
①计算机执行递归时,会用栈维护入栈、出栈的过程
②层序遍历,需要手动实现入队、出队的代码
102. 二叉树的层序遍历
【题目】
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
示例 1:
输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]
示例 2:
输入:root = [1]
输出:[[1]]
示例 3:
输入:root = []
输出:[]
提示:
树中节点数目在范围 [0, 2000] 内
-1000 <= Node.val <= 1000
【核心思路】
结果列表res的每个元素存放每一层的所有节点
两个方法思路相同
法1:BFS
①定义三个列表,cur(存储当前遍历这层的节点)、nxt(存储下一层的节点)、val(存储当前遍历的节点对应的节点值)
②每次先遍历cur的所有节点,并将当前遍历的那个节点的值加入val,然后将当前节点的所有孩子(若存在)加入nxt
③当前层遍历完后,nxt替换cur,从而遍历下一层的所有节点
④以此类推,直至cur为空
法2:队列(更好)
①定义一个队列、一个列表:q(先入队先访问并出队)、val(当前遍历的节点对应的节点值)
②每次遍历队头元素,并将它的值加入val,然后将当前节点的所有孩子(若存在)加入队列
③当前层遍历完后,从而遍历下一层的所有节点
④以此类推,直至q为空
【复杂度】
时间复杂度:O(n)O(n)O(n)。n=总节点数
空间复杂度:O(n)O(n)O(n)。满二叉树的最后一层最多约n/2个节点
【代码】法1
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val = val; }* TreeNode(int val, TreeNode left, TreeNode right) {* this.val = val;* this.left = left;* this.right = right;* }* }*/
class Solution {public List<List<Integer>> levelOrder(TreeNode root) {//三个列表:cur(当前这层的节点)、nxt(下一层的节点)、val(当前遍历的节点对应的节点值)//循环终止条件:cur为空//当前节点为空,直接返回if (root == null) {return new ArrayList<>();}//初始化结果列表List<List<Integer>> res = new ArrayList<>();//初始化列表List<TreeNode> cur = new ArrayList<>();cur.add(root);//遍历cur列表while (!cur.isEmpty()) {//定义nxt列表List<TreeNode> nxt = new ArrayList<>();//定义val列表List<Integer> val = new ArrayList<>();//遍历当前这层的每个节点for (TreeNode node : cur) {//将当前遍历的节点值加入valval.add(node.val);//将当前遍历的节点的左右孩子加入nxtif (node != null && node.left != null) {nxt.add(node.left);}if (node != null && node.right != null) {nxt.add(node.right);}}//将cur更新为nxtcur = nxt;//将val加入结果列表res.add(val);}return res;}
}
【代码】法2
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val = val; }* TreeNode(int val, TreeNode left, TreeNode right) {* this.val = val;* this.left = left;* this.right = right;* }* }*/
class Solution {public List<List<Integer>> levelOrder(TreeNode root) {//一个队列、一个列表:q(先入队先访问并出队)、val(当前遍历的节点对应的节点值)//循环终止条件:q为空//当前节点为空,直接返回if (root == null) {return new ArrayList<>();}//初始化结果列表List<List<Integer>> res = new ArrayList<>();//初始化队列Queue<TreeNode> q = new ArrayDeque<>();q.add(root);//遍历队列while (!q.isEmpty()) {//定义val列表List<Integer> val = new ArrayList<>();//获取队列长度int len = q.size();//遍历while (len-- > 0) {//出队TreeNode node = q.poll();//将当前遍历的节点值加入valval.add(node.val);//将当前遍历的节点的左右孩子加入队列if (node != null && node.left != null) {q.add(node.left);}if (node != null && node.right != null) {q.add(node.right);}}//将val加入结果列表res.add(val);}return res;}
}
103. 二叉树的锯齿形层序遍历
【题目】
给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。
示例 1:
输入:root = [3,9,20,null,null,15,7]
输出:[[3],[20,9],[15,7]]
示例 2:
输入:root = [1]
输出:[[1]]
示例 3:
输入:root = []
输出:[]
提示:
树中节点数目在范围 [0, 2000] 内
-100 <= Node.val <= 100
【核心思路】
基于#102,将偶数层的val翻转
【复杂度】
时间复杂度:O(n)O(n)O(n)。n=总节点数
空间复杂度:O(n)O(n)O(n)。最坏情况下,退化成一条链
【代码】法2
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val = val; }* TreeNode(int val, TreeNode left, TreeNode right) {* this.val = val;* this.left = left;* this.right = right;* }* }*/
class Solution {public List<List<Integer>> zigzagLevelOrder(TreeNode root) {//一个队列、一个列表:q(先入队先访问并出队)、val(当前遍历的节点对应的节点值)//循环终止条件:q为空//若是偶数层,将val翻转//当前节点为空,直接返回if (root == null) {return new ArrayList<>();}//初始化结果列表List<List<Integer>> res = new ArrayList<>();//初始化队列Queue<TreeNode> q = new ArrayDeque<>();q.add(root);//标记是否是偶数层boolean flag = false;//遍历队列while (!q.isEmpty()) {//定义val列表List<Integer> val = new ArrayList<>();//获取队列长度int len = q.size();//遍历while (len-- > 0) {//出队TreeNode node = q.poll();//将当前遍历的节点值加入valval.add(node.val);//将当前遍历的节点的左右孩子加入队列if (node != null && node.left != null) {q.add(node.left);}if (node != null && node.right != null) {q.add(node.right);}}//翻转valif (flag) {Collections.reverse(val);}//更新flagflag = !flag;//将val加入结果列表res.add(val);}return res;}
}
513. 找树左下角的值
【题目】
给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。
假设二叉树中至少有一个节点。
示例 1:
输入: root = [2,1,3]
输出: 1
示例 2:
输入: [1,2,3,4,null,5,6,null,null,7]
输出: 7
提示:
二叉树的节点个数的范围是 [1,10410^4104]
−231-2^31−231 <= Node.val <= 231−12^31-1231−1
【核心思路】同#103
与#103、#102区别:①无需res、val;②题目保证至少一个节点,无需判断当前节点为空的情况
【复杂度】
时间复杂度:O(n)O(n)O(n)。n=总节点数
空间复杂度:O(n)O(n)O(n)。最坏情况下,退化成一条链
【代码】
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val = val; }* TreeNode(int val, TreeNode left, TreeNode right) {* this.val = val;* this.left = left;* this.right = right;* }* }*/
class Solution {public int findBottomLeftValue(TreeNode root) {//一个队列:q(先入队先访问并出队)//循环终止条件:q为空//右孩子先入队,左孩子后入队,最后一个出队的节点就是答案//与#103、#102区别:①无需res、val//②题目保证至少一个节点,无需判断当前节点为空的情况//初始化队列Queue<TreeNode> q = new ArrayDeque<>();TreeNode node = root;q.add(node);//遍历队列while (!q.isEmpty()) {//获取队列长度int len = q.size();//遍历while (len-- > 0) {//出队node = q.poll();//将当前遍历的节点的右左孩子加入队列if (node != null && node.right != null) {q.add(node.right);}if (node != null && node.left != null) {q.add(node.left);}}}//最后一个节点(内循环最后一次出队的节点)就是答案return node.val;}
}
参考:
1、灵神题解
2、灵神视频讲解