层序遍历
题目链接:
学会二叉树的层序遍历,可以一口气打完以下十题:
- 102.二叉树的层序遍历
- 107.二叉树的层次遍历II
- 199.二叉树的右视图
- 637.二叉树的层平均值
- 429.N叉树的层序遍历
- 515.在每个树行中找最大值
- 116.填充每个节点的下一个右侧节点指针
- 117.填充每个节点的下一个右侧节点指针II
- 104.二叉树的最大深度
- 111.二叉树的最小深度
文档讲解:https://programmercarl.com/0102.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E5%B1%82%E5%BA%8F%E9%81%8D%E5%8E%86.html
视频讲解:https://www.bilibili.com/video/BV1GY4y1u7b2
思路(层序遍历)
使用队列来辅助遍历。记录每一层的个数,然后弹出一个节点,就把他的左右孩子放进队列中。当这一层的个数为0,就开始遍历下一行。
代码
102.二叉树的层序遍历
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
if (root == null) return res;
Deque<TreeNode> deque = new LinkedList<>();
deque.push(root);
while (!deque.isEmpty()) {
List<Integer> temp = new ArrayList<>();
int size = deque.size();
while(size-- > 0) {
TreeNode cur = deque.pollFirst();
temp.add(cur.val);
if (cur.left != null) deque.addLast(cur.left);
if (cur.right != null) deque.addLast(cur.right);
}
res.add(temp);
}
return res;
}
}
107.二叉树的层次遍历 II
class Solution {
public List<List<Integer>> levelOrderBottom(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
if (root == null) return res;
Deque<TreeNode> deque = new LinkedList<>();
deque.addLast(root);
while (!deque.isEmpty()) {
int size = deque.size();
List<Integer> temp = new ArrayList<>();
while (size-- > 0) {
TreeNode node = deque.pollFirst();
temp.add(node.val);
if (node.left != null) deque.addLast(node.left);
if (node.right != null) deque.addLast(node.right);
}
res.add(temp);
}
Collections.reverse(res); // 翻转数组
return res;
}
}
199.二叉树的右视图
class Solution {
public List<Integer> rightSideView(TreeNode root) {
List<Integer> res = new ArrayList<>();
if (root == null) return res;
Deque<TreeNode> deque = new LinkedList<>();
deque.addLast(root);
while (!deque.isEmpty()) {
int size = deque.size();
while (size-- > 0) {
TreeNode node = deque.pollFirst();
if (node.left != null) deque.addLast(node.left);
if (node.right != null) deque.addLast(node.right);
if (size == 0) res.add(node.val); // 遍历到本层最后一个节点再放入数组中
}
}
return res;
}
}
637.二叉树的层平均值
class Solution {
public List<Double> averageOfLevels(TreeNode root) {
List<Double> res = new ArrayList<>();
Deque<TreeNode> deque = new LinkedList<>();
deque.addLast(root);
while (!deque.isEmpty()) {
int size = deque.size();
int size2 = deque.size();
Double sum = 0D;
while (size-- > 0) {
TreeNode node = deque.pollFirst();
sum += node.val;
if (node.left != null) deque.addLast(node.left);
if (node.right != null) deque.addLast(node.right);
}
res.add(sum / size2);
}
return res;
}
}
429.N叉树的层序遍历
class Solution {
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> res = new ArrayList<>();
if (root == null) return res;
Deque<Node> deque = new LinkedList<>();
deque.addLast(root);
while(!deque.isEmpty()) {
int size = deque.size();
List<Integer> temp = new ArrayList<>();
while (size-- > 0) {
Node node = deque.pollFirst();
temp.add(node.val);
for (Node child : node.children) { // 这里放入孩子节点的list,而不是左孩子和右孩子
deque.addLast(child);
}
}
res.add(temp);
}
return res;
}
}
515.在每个树行中找最大值
class Solution {
public List<Integer> largestValues(TreeNode root) {
List<Integer> res = new ArrayList<>();
if (root == null) return res;
Deque<TreeNode> deque = new LinkedList<>();
deque.addLast(root);
while (!deque.isEmpty()) {
int size = deque.size();
int max = Integer.MIN_VALUE;
while (size-- > 0) {
TreeNode node = deque.pollFirst();
max = Math.max(max, node.val);
if (node.left != null) deque.addLast(node.left);
if (node.right != null) deque.addLast(node.right);
}
res.add(max);
}
return res;
}
}
116.填充每个节点的下一个右侧节点指针
class Solution {
public Node connect(Node root) {
if (root == null) return root;
Deque<Node> deque = new LinkedList<>();
deque.addLast(root);
while (!deque.isEmpty()) {
int size = deque.size();
while (size-- > 0) {
Node node1 = deque.pollFirst();
Node node2 = deque.peekFirst(); // 获得下一个节点的信息
if (size == 0) node1.next = null;
else node1.next = node2;
if (node1.left != null) deque.addLast(node1.left);
if (node1.right != null) deque.addLast(node1.right);
}
}
return root;
}
}
117.填充每个节点的下一个右侧节点指针II
这道题目说是二叉树,上面的116题目说是完整二叉树,116的代码有判断左右孩子是否为空,所以这道题代码和116是一样的。
104.二叉树的最大深度
class Solution {
public int maxDepth(TreeNode root) {
int res = 0;
if (root == null) return res;
Deque<TreeNode> deque = new LinkedList<>();
deque.addLast(root);
while (!deque.isEmpty()) {
int size = deque.size();
while (size-- > 0) {
TreeNode node = deque.pollFirst();
if (node.left != null) deque.addLast(node.left);
if (node.right != null) deque.addLast(node.right);
}
res++;
}
return res;
}
}
111.二叉树的最小深度
class Solution {
public int minDepth(TreeNode root) {
int depth = 0;
if (root == null) return depth;
Deque<TreeNode> deque = new LinkedList<>();
deque.addLast(root);
while (!deque.isEmpty()) {
int size = deque.size();
while (size-- > 0) {
TreeNode node = deque.pollFirst();
if (node.left != null) deque.addLast(node.left);
if (node.right != null) deque.addLast(node.right);
if (node.left == null && node.right == null) return depth + 1; // 当左右孩子都为空,直接返回最小深度
}
depth++;
}
return depth;
}
}
226.翻转二叉树
题目链接:https://leetcode.cn/problems/invert-binary-tree/
文档讲解:https://programmercarl.com/0226.%E7%BF%BB%E8%BD%AC%E4%BA%8C%E5%8F%89%E6%A0%91.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE
视频讲解:https://www.bilibili.com/video/BV1sP4y1f7q7
思路
- 确定递归函数的参数和返回值。
参数就是要传入节点的指针,不需要其他参数了,通常此时定下来主要参数,如果在写递归的逻辑中发现还需要其他参数的时候,随时补充。
返回值的话其实也不需要,但是题目中给出的要返回root节点的指针,可以直接使用题目定义好的函数,所以就函数的返回类型为TreeNode。
public TreeNode invertTree(TreeNode root)
- 确定终止条件。
当前节点为空的时候,就返回。
if (root == null) return root;
- 确定单层递归的逻辑。
// 因为是前序遍历,所以先进行交换左右孩子节点,然后反转左子树,反转右子树。
swapChildren(root);
invertTree(root.left);
invertTree(root.right);
// 后序遍历就交换一下顺序。
swapChildren(root);
invertTree(root.left);
invertTree(root.right);
// 如果是中序遍历,是左-中-左,如果是左中右的话,翻转的右孩子就是之前翻转过来的左孩子。
invertTree(root.left);
swapChildren(root);
invertTree(root.left);
代码
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null) return root;
swapChildren(root);
invertTree(root.left);
invertTree(root.right);
return root;
}
public void swapChildren(TreeNode root) {
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
}
}
101.对称二叉树
题目链接:https://leetcode.cn/problems/symmetric-tree/
文档讲解:https://programmercarl.com/0101.%E5%AF%B9%E7%A7%B0%E4%BA%8C%E5%8F%89%E6%A0%91.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE
视频讲解:https://www.bilibili.com/video/BV1ue4y1Y7Mf
思路
这道题只能用后序遍历,因为需要得到左右子树是否对称以后,返回给中间节点。
- 确定递归函数的参数和返回值。
因为我们要比较的是根节点的两个子树是否是相互翻转的,进而判断这个树是不是对称树,所以要比较的是两个树,参数自然也是左子树节点和右子树节点。返回值自然是boolean类型。
boolean compare(TreeNode left, TreeNode right)
- 确定终止条件。
要比较两个节点数值相不相同,首先要把两个节点为空的情况弄清楚,否则后面比较数值的时候就会操作空指针了。
节点为空的情况有:
- 左节点为空,右节点不为空,不对称,return false
- 左不为空,右为空,不对称 return false
- 左右都为空,对称,返回true
此时已经排除掉了节点为空的情况,那么剩下的就是左右节点不为空:
- 左右都不为空,比较节点数值,不相同就return false
- 此时左右节点不为空,且数值也不相同的情况我们也处理了。
if (left == null && right == null) return true;
else if (left == null && right != null) return false;
else if (left != null && right == null) return false;
else if (left.val != right.val) return false;
注意上面最后一种情况,没有使用else,而是else if, 因为我们把以上情况都排除之后,剩下的就是左右节点都不为空,且数值相同的情况。
- 确定单层递归的逻辑
此时才进入单层递归的逻辑,单层递归的逻辑就是处理 左右节点都不为空,且数值相同的情况。
比较二叉树外侧是否对称:传入的是左节点的左孩子,右节点的右孩子。
比较内侧是否对称,传入左节点的右孩子,右节点的左孩子。
如果左右都对称就返回true ,有一侧不对称就返回false 。
boolean outside = compare(left.left, right.right);
boolean inside = compare(left.right, right.left);
boolean res = outside && inside;
return res;
代码
class Solution {
public boolean isSymmetric(TreeNode root) {
return compare(root.left, root.right);
}
public boolean compare(TreeNode left, TreeNode right) {
if (left == null && right == null) return true;
else if (left == null && right != null) return false;
else if (left != null && right == null) return false;
else if (left.val != right.val) return false;
boolean outside = compare(left.left, right.right);
boolean inside = compare(left.right, right.left);
boolean res = outside && inside;
return res;
}
}
标签:node,deque,right,root,随想录,二叉树,null,第十五天,left
From: https://blog.csdn.net/Danny_8/article/details/139150482