⚡刷题计划day13 二叉树(二)继续,任务2道例题然后还有10道类似题,可以点个免费的赞哦~
102.二叉树的层序遍历
上一小节我们练习遍历的其实也是深度优先遍历,而接下来我们会介绍二叉树的另一种遍历方式:层序遍历,对应就是图论中的广度优先遍历
-
二叉树的层序遍历
(https://leetcode.cn/problems/binary-tree-level-order-traversal/description/)
法一:队列
我们之前迭代遍历是用栈先进后出模拟深度优先遍历,同样对于层序遍历可以使用队列先进先出的逻辑来模拟。
辅助理解动画如下,详细见代码注释:
public void bfs2(TreeNode node) {
// 如果根节点为空,直接返回
if (node == null) return;
// 创建一个队列,用于存储待遍历的节点
Queue<TreeNode> que = new LinkedList<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);
}
}
法二:递归
关于递归逻辑上期有讲,主要注意三个要素即可:
1.确定递归函数的参数和返回值
2.确定终止条件
3.确定单层递归的逻辑
AC代码及注释如下:
class Solution {
List<List<Integer>> resList = new ArrayList<List<Integer>>();
public List<List<Integer>> levelOrder(TreeNode root) {
bfs1(root,0);
return resList;
}
public void bfs1(TreeNode node,Integer deep){
if(node == null) return;
deep++;
if(resList.size()<deep){
//当层级增加时,list的Item也增加,利用list的索引值进行层级界定
List<Integer> item = new ArrayList<>();
resList.add(item);
}
// 将当前节点的值添加到对应层级的列表中
resList.get(deep-1).add(node.val);
bfs1(node.left,deep);
bfs1(node.right,deep);
}
}
有兴趣的,可以直接拿下这十道题:
学会二叉树的层序遍历,可以一口气打完以下十题:
226.翻转二叉树
-
翻转二叉树
(https://leetcode.cn/problems/invert-binary-tree/description/)
如图翻转,也是很经典的一道题,可以运用我们之前的各种遍历方法实现:
可以发现,把每一个节点的左右孩子交换一下,就可以达到整体翻转的效果。
这道题目使用前序遍历和后序遍历都可以,唯独中序遍历不方便,因为中序遍历会把某些节点的左右孩子翻转了两次!建议拿纸画一画,就理解了
那么层序遍历可以不可以呢?依然可以的!只要把每一个节点的左右孩子翻转一下的遍历方式都是可以的!
废话不多说,上代码!
法一:层序遍历法(bfs)
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root==null) return null;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()){
int size = queue.size();
for (int i=0;i<size;i++){
TreeNode tmpNode = queue.poll();
swap(tmpNode);
if(tmpNode.left!=null) queue.offer(tmpNode.left);
if (tmpNode.right!=null) queue.offer(tmpNode.right);
}
}
return root;
}
public void swap(TreeNode node){
TreeNode temp = node.left;
node.left = node.right;
node.right = temp;
}
}
法二:迭代遍历(dfs)
前后序遍历都可以
中序不行,因为先左孩子交换孩子,再根交换孩子(做完后,右孩子已经变成了原来的左孩子),再右孩子交换孩子(此时其实是对原来的左孩子做交换)
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root==null) return null;
swap(root);
invertTree(root.left);
invertTree(root.right);
return root;
}
public void swap(TreeNode node){
TreeNode tmp = node.left;
node.left = node.right;
node.right = tmp;
}
}
欢迎点赞收藏关注~