目录
递归遍历和迭代遍历:
144.二叉树的前序遍历
94.二叉树的中序遍历
145.二叉树的后序遍历
层序遍历:
102.二叉树的层序遍历
107.二叉树的层序遍历Ⅱ
199.二叉树的右视图
637.二叉树的层平均值
429.N叉树的层序遍历
515.在每个树行中找最大值
116.填充每个节点的下一个右侧节点指针
117.填充每个节点的下一个右侧节点指针Ⅱ
104.二叉树的最大深度
111.二叉树的最小深度
144.二叉树的前序遍历
题目
144. 二叉树的前序遍历 - 力扣(LeetCode)
给你二叉树的根节点 root
,返回它节点值的 前序 遍历。
示例1:
输入:root = [1,null,2,3]
输出:[1,2,3]
示例2:
输入:root = [1,2,3,4,5,null,8,null,null,6,7,9]
输出:[1,2,4,5,6,7,3,8,9]
示例3:
输入:root = []
输出:[]
示例4:
输入:root = [1]
输出:[1]
提示:
- 树中节点数目在范围
[0, 100]
内 -100 <= Node.val <= 100
思路
代码随想录:二叉树的递归遍历
代码随想录:二叉树的迭代遍历
视频讲解:LeetCode:144.前序遍历,145.后序遍历,94.中序遍历
视频讲解:二叉树的遍历迭代法 | 前序与后序
分别使用递归法和迭代法解题。
迭代法使用栈实现,前序遍历实现如下:
- 初始化一个空栈,并将根节点压入栈中。
- 当栈不为空时,弹出栈顶节点,访问该节点,并依次将其右孩子和左孩子节点压入栈中(因为栈是后进先出,所以左孩子会先被处理)。
- 重复步骤2,直到栈为空。
题解
递归法:
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
preorder(res, root);
return res;
}
void preorder(List list, TreeNode root) {
if (root == null)
return;
list.add(root.val);
if (root.left != null)
preorder(list, root.left);
if (root.right != null)
preorder(list, root.right);
}
}
迭代法:
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
Deque<TreeNode> deque = new ArrayDeque<>();
if(root!=null){
deque.push(root);
}
while(!deque.isEmpty()){
TreeNode tmp = deque.pop();
res.add(tmp.val);
if(tmp.right!=null)
deque.push(tmp.right);
if(tmp.left!=null)
deque.push(tmp.left);
}
return res;
}
}
94.二叉树的中序遍历
题目
94. 二叉树的中序遍历 - 力扣(LeetCode)
给定一个二叉树的根节点 root
,返回 它的 中序 遍历 。
示例1:
输入:root = [1,null,2,3]
输出:[1,3,2]
示例2:
输入:root = []
输出:[]
示例3:
输入:root = [1]
输出:[1]
提示:
- 树中节点数目在范围
[0, 100]
内 -100 <= Node.val <= 100
思路
代码随想录:二叉树的递归遍历
代码随想录:二叉树的迭代遍历
视频讲解:LeetCode:144.前序遍历,145.后序遍历,94.中序遍历
视频讲解:二叉树的遍历迭代法 | 中序
同样使用栈来实现迭代法,步骤如下:
- 初始化一个空栈,将当前节点设为根节点。
- 当当前节点不为空时,将其压入栈中,并将当前节点设为其左孩子。
- 如果当前节点为空,弹出栈顶节点,访问该节点,然后将当前节点设为其右孩子。
- 重复上述步骤,直到栈为空并且当前节点也为空。
题解
递归法:
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
inorder(res, root);
return res;
}
void inorder(List list, TreeNode root) {
if (root == null)
return;
if (root.left != null)
inorder(list, root.left);
list.add(root.val);
if (root.right != null)
inorder(list, root.right);
}
}
迭代法:
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
Deque<TreeNode> deque = new ArrayDeque<>();
TreeNode cur = root;
while (cur != null || !deque.isEmpty()) {
if (cur != null) {
deque.push(cur);
cur = cur.left;
} else {
cur = deque.pop();
res.add(cur.val);
cur = cur.right;
}
}
return res;
}
}
145.二叉树的后序遍历
题目
145. 二叉树的后序遍历 - 力扣(LeetCode)
给你一棵二叉树的根节点 root
,返回其节点值的 后序遍历 。
示例1:
输入:root = [1,null,2,3]
输出:[3,2,1]
示例2:
输入:root = [1,2,3,4,5,null,8,null,null,6,7,9]
输出:[4,6,7,5,2,9,8,3,1]
示例3:
输入:root = []
输出:[]
示例4:
输入:root = [1]
输出:[1]
提示:
- 树中节点的数目在范围
[0, 100]
内 -100 <= Node.val <= 100
思路
代码随想录:二叉树的递归遍历
代码随想录:二叉树的迭代遍历
视频讲解:LeetCode:144.前序遍历,145.后序遍历,94.中序遍历
视频讲解:二叉树的遍历迭代法 | 前序与后序
迭代法:
具体步骤如下所示:
- 初始化一个空栈,将根节点入栈,使用一个变量
prev
初始化为null
,用来追踪上一个已访问的节点。 - 当栈不为空时,查看栈顶节点
cur
。 - 若栈顶节点
cur
没有左孩子和右孩子,或prev
是其左孩子或右孩子(即左右子树都已被访问过),则弹出cur
,并添加到结果中,然后将prev
设为cur
。 - 若不满足条件3,按顺序将其右孩子和左孩子压入栈,确保左孩子先被访问。
- 重复步骤2-4,直到栈为空
题解
递归法:
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
postorder(res, root);
return res;
}
void postorder(List list, TreeNode root) {
if (root == null)
return;
if (root.left != null)
postorder(list, root.left);
if (root.right != null)
postorder(list, root.right);
list.add(root.val);
}
}
迭代法:
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
Deque<TreeNode> deque = new ArrayDeque<>();
TreeNode cur = root;
TreeNode prev = null;
while (!deque.isEmpty() || cur != null) {
while (cur != null) {
deque.push(cur);
cur = cur.left;
}
cur = deque.peek();
if (cur.right == null || cur.right == prev) {
res.add(cur.val);
deque.pop();
prev = cur;
cur = null;
} else {
cur = cur.right;
}
}
return res;
}
}
102.二叉树的层序遍历
题目
102. 二叉树的层序遍历 - 力扣(LeetCode)
给你二叉树的根节点 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
思路
代码随想录:102.二叉树的层序遍历
视频讲解:LeetCode:102.二叉树的层序遍历
层序遍历二叉树,就是从左到右一层一层的去遍历二叉树,需要借用队列来实现,队列先进先出,符合一层一层遍历的逻辑。
使用队列实现二叉树广度优先遍历过程如下:
初始化:
- 创建一个空队列
queue
,并将根节点root
入队。 - 如果
root
为null
,直接返回空列表。
主循环:
- 当队列不为空时,执行以下操作:
- 从队列中取出队首节点
node
并将其值添加到结果列表。 - 若
node
有左孩子,将左孩子入队。 - 若
node
有右孩子,将右孩子入队。
- 从队列中取出队首节点
重复上述过程,直到队列为空。
题解
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
Deque<TreeNode> deque = new ArrayDeque<>();
if (root == null)
return res;
deque.push(root);
while (!deque.isEmpty()) {
int size = deque.size();
List<Integer> list = new ArrayList<>();
while (size-- > 0) {
TreeNode node = deque.poll();
list.add(node.val);
if (node.left != null)
deque.offer(node.left);
if (node.right != null)
deque.offer(node.right);
}
res.add(list);
}
return res;
}
}
107.二叉树的层序遍历 Ⅱ
题目
107. 二叉树的层序遍历 II - 力扣(LeetCode)
给你二叉树的根节点 root
,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
示例1:
输入:root = [3,9,20,null,null,15,7]
输出:[[15,7],[9,20],[3]]
思路
代码随想录:107.二叉树的层序遍历Ⅱ
思路如102. 二叉树的层序遍历 - 力扣(LeetCode),最后使用 Collections.reverse()
翻转即可。
题解
class Solution {
public List<List<Integer>> levelOrderBottom(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
Deque<TreeNode> deque = new ArrayDeque<>();
if (root == null)
return res;
deque.push(root);
while (!deque.isEmpty()) {
int size = deque.size();
List<Integer> list = new ArrayList<>();
while (size-- > 0) {
TreeNode node = deque.poll();
list.add(node.val);
if (node.left != null)
deque.offer(node.left);
if (node.right != null)
deque.offer(node.right);
}
res.add(list);
}
Collections.reverse(res);
return res;
}
}
199.二叉树的右视图
题目
199. 二叉树的右视图 - 力扣(LeetCode)
给定一个二叉树的 根节点 root
,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
示例1:
输入: [1,2,3,null,5,null,4]
输出: [1,3,4]
示例2:
输入: [1,2,3,4]
输出: [1,3,4]
思路
代码随想录:199.二叉树的右视图
在普通层序遍历的基础上,将入队顺序改为右孩子先入,再添加一个结果判断条件,只有在保证该元素是这一层最右边的元素时,才将其添加到结果列表。
题解
class Solution {
public List<Integer> rightSideView(TreeNode root) {
List<Integer> res = new ArrayList<>();
Deque<TreeNode> deque = new ArrayDeque<>();
if (root == null)
return res;
deque.offer(root);
while (!deque.isEmpty()) {
int size = deque.size();
for (int i = 0; i < size; i++) {
TreeNode node = deque.poll();
if (node.right != null)
deque.offer(node.right);
if (node.left != null)
deque.offer(node.left);
if (i == 0) {
res.add(node.val);
}
}
}
return res;
}
}
637.二叉树的层平均值
题目
637. 二叉树的层平均值 - 力扣(LeetCode)
给定一个非空二叉树的根节点 root
, 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5 以内的答案可以被接受。
思路
代码随想录:637.二叉树的层平均值
层序遍历后求每一层平均值。
题解
class Solution {
public List<Double> averageOfLevels(TreeNode root) {
List<Double> res = new ArrayList<>();
Deque<TreeNode> deque = new ArrayDeque<>();
if (root == null)
return res;
deque.offer(root);
while (!deque.isEmpty()) {
int size = deque.size();
double sum = 0.0;
for (int i = 0; i < size; i++) {
TreeNode node = deque.poll();
if (node.left != null)
deque.offer(node.left);
if (node.right != null)
deque.offer(node.right);
sum += node.val;
}
res.add(sum / size);
}
return res;
}
}
429.N叉树的层序遍历
题目
429. N 叉树的层序遍历 - 力扣(LeetCode)
给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。
示例1:
输入:root = [1,null,3,2,4,null,5,6]
输出:[[1],[3,2,4],[5,6]]
示例2:
输入:root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14]
输出:[[1],[2,3,4,5],[6,7,8,9,10],[11,12,13],[14]]
提示:
- 树的高度不会超过
1000
- 树的节点总数在
[0, 104]
之间
思路
代码随想录:429.N叉树的层序遍历
层序遍历时一个节点有多个孩子。
题解
class Solution {
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> res = new ArrayList<>();
Deque<Node> deque = new ArrayDeque<>();
if (root == null)
return res;
deque.offer(root);
while (!deque.isEmpty()) {
int size = deque.size();
List<Integer> list = new ArrayList<>();
for (int i = 0; i < size; i++) {
Node node = deque.poll();
list.add(node.val);
List<Node> children = node.children;
//对列表使用增强for循环
for (Node child : children) {
if (child != null)
deque.offer(child);
}
}
res.add(list);
}
return res;
}
}
515. 在每个树行中找最大值
题目
515. 在每个树行中找最大值 - 力扣(LeetCode)
给定一棵二叉树的根节点 root
,请找出该二叉树中每一层的最大值。
示例1:
输入: root = [1,3,2,5,3,null,9]
输出: [1,3,9]
示例2:
输入: root = [1,2,3]
输出: [1,3]
提示:
- 二叉树的节点个数的范围是
[0,104]
-231 <= Node.val <= 231 - 1
思路
代码随想录:515.在每个树行中找最大值
层序遍历,注意定义max时可以设置为 Integer.MIN_VALUE
。
题解
class Solution {
public List<Integer> largestValues(TreeNode root) {
List<Integer> res = new ArrayList<>();
Deque<TreeNode> deque = new ArrayDeque<>();
if (root == null)
return res;
deque.offer(root);
while (!deque.isEmpty()) {
int size = deque.size();
int max = Integer.MIN_VALUE;
for (int i = 0; i < size; i++) {
TreeNode node = deque.poll();
max = Math.max(max, node.val);
if (node.left != null)
deque.offer(node.left);
if (node.right != null)
deque.offer(node.right);
}
res.add(max);
}
return res;
}
}
116. 填充每个节点的下一个右侧节点指针
题目
116. 填充每个节点的下一个右侧节点指针 - 力扣(LeetCode)
给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL
。
初始状态下,所有 next 指针都被设置为 NULL
。
示例1:
输入:root = [1,2,3,4,5,6,7]
输出:[1,#,2,3,#,4,5,6,7,#]
解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化的输出按层序遍历排列,同一层节点由 next 指针连接,'#' 标志着每一层的结束。
提示:
- 树中节点的数量在
[0, 212 - 1]
范围内 -1000 <= node.val <= 1000
思路
代码随想录:116.填充每个节点的下一个右侧节点指针
常见的层序遍历。
题解
class Solution {
public Node connect(Node root) {
Deque<Node> deque = new ArrayDeque<>();
if (root == null)
return root;
deque.offer(root);
while (!deque.isEmpty()) {
int size = deque.size();
for (int i = 0; i < size; i++) {
Node node = deque.poll();
if (i < size - 1)
node.next = deque.peek();
if (node.left != null)
deque.offer(node.left);
if (node.right != null)
deque.offer(node.right);
}
}
return root;
}
}
117. 填充每个节点的下一个右侧节点指针 Ⅱ
题目
117. 填充每个节点的下一个右侧节点指针 II - 力扣(LeetCode)
给定一个二叉树:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL
。
初始状态下,所有 next 指针都被设置为 NULL
。
示例1:
输入:root = [1,2,3,4,5,null,7]
输出:[1,#,2,3,#,4,5,7,#]
解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化输出按层序遍历顺序(由 next 指针连接),'#' 表示每层的末尾。
提示:
- 树中的节点数在范围
[0, 6000]
内 -100 <= Node.val <= 100
思路
代码随想录:117.填充每个节点的下一个右侧节点指针Ⅱ
完全一致:116. 填充每个节点的下一个右侧节点指针 - 力扣(LeetCode)
题解
class Solution {
public Node connect(Node root) {
Deque<Node> deque = new ArrayDeque<>();
if (root == null)
return root;
deque.offer(root);
while (!deque.isEmpty()) {
int size = deque.size();
for (int i = 0; i < size; i++) {
Node node = deque.poll();
if (i < size - 1)
node.next = deque.peek();
if (node.left != null)
deque.offer(node.left);
if (node.right != null)
deque.offer(node.right);
}
}
return root;
}
}
104.二叉树的最大深度
题目
104. 二叉树的最大深度 - 力扣(LeetCode)
给定一个二叉树 root
,返回其最大深度。
二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。
示例1:
输入:root = [3,9,20,null,null,15,7]
输出:3
思路
代码随想录:104.二叉树的最大深度
此题除了层序遍历之外,还可以使用递归法。
树的深度等于左子树深度和右子树深度中的最大值+1。
-
递归终止条件:当前节点为空
-
找出返回值:节点为空时说明子树高度为 0,返回 0,节点不为空时则分别求左右子树的高度,取两者中的最大值加 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 int maxDepth(TreeNode root) {
int res = 0;
Deque<TreeNode> deque = new ArrayDeque<>();
if (root == null)
return res;
deque.offer(root);
while (!deque.isEmpty()) {
int size = deque.size();
for (int i = 0; i < size; i++) {
TreeNode node = deque.poll();
if (node.left != null)
deque.offer(node.left);
if (node.right != null)
deque.offer(node.right);
}
res++;
}
return res;
}
}
递归法:
class Solution {
public int maxDepth(TreeNode root) {
if (root == null) {
return 0;
} else {
int left = maxDepth(root.left);
int right = maxDepth(root.right);
return Math.max(left, right) + 1;
}
}
}
111.二叉树的最小深度
题目
111. 二叉树的最小深度 - 力扣(LeetCode)
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明: 叶子节点是指没有子节点的节点。
示例1:
输入:root = [3,9,20,null,null,15,7]
输出:2
提示:
- 树中节点数的范围在
[0, 105]
内 -1000 <= Node.val <= 1000
思路
代码随想录:111.二叉树的最小深度
层序遍历,当左右孩子都为空时才能说明遍历到最低点。
题解
/**
* 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 minDepth(TreeNode root) {
int res = 0;
Deque<TreeNode> deque = new ArrayDeque<>();
if (root == null)
return res;
deque.offer(root);
res++;
while (!deque.isEmpty()) {
int size = deque.size();
for (int i = 0; i < size; i++) {
TreeNode node = deque.poll();
if (node.left == null && node.right == null)
return res;
if (node.left != null)
deque.offer(node.left);
if (node.right != null)
deque.offer(node.right);
}
res++;
}
return res;
}
}