第六章 二叉树part04
110.平衡二叉树 (优先掌握递归)
再一次涉及到,什么是高度,什么是深度,可以巩固一下。
题目链接/文章讲解/视频讲解:https://programmercarl.com/0110.%E5%B9%B3%E8%A1%A1%E4%BA%8C%E5%8F%89%E6%A0%91.html
思考:
步骤:
- 定义二叉树节点类
TreeNode
,包括值val
、左子树left
和右子树right
。 - 创建
BalancedBinaryTree
类,其中包含一个isBalanced
方法用于判断二叉树是否是高度平衡的。 - 在
isBalanced
方法中,先判断当前节点是否为空,若是则返回true,因为空树是高度平衡的。 - 分别计算当前节点的左子树和右子树的高度,可以通过一个辅助方法
getHeight
实现。 - 判断当前节点的左右子树高度差是否不超过1,并且左右子树也是高度平衡的,若满足条件则返回true,否则返回false。
- 在
getHeight
方法中,递归计算左右子树的高度,并返回较大值加上当前节点1作为当前节点的高度。 - 在
main
方法中,构建一棵高度平衡的二叉树,并调用isBalanced
方法判断是否是高度平衡的。 - 输出结果。
- 运行程序,得到判断结果。
注意事项:
- 对于空树,直接返回true。
- 对于非空树,需要计算当前节点的左右子树高度差是否不超过1,并且递归判断左右子树是否也是高度平衡的。
- 需要注意空节点的高度为0。
完整代码
// 定义二叉树节点类
class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode(int val) {
this.val = val;
}
}
public class BalancedBinaryTree {
public boolean isBalanced(TreeNode root) {
if (root == null) {
return true; // 空树是高度平衡的
}
int leftHeight = getHeight(root.left); // 计算左子树高度
int rightHeight = getHeight(root.right); // 计算右子树高度
// 判断当前节点的左右子树高度差是否不超过1,并且左右子树也是高度平衡的
return Math.abs(leftHeight - rightHeight) <= 1 && isBalanced(root.left) && isBalanced(root.right);
}
private int getHeight(TreeNode node) {
if (node == null) {
return 0; // 空节点高度为0
}
// 递归计算左右子树的高度,并返回较大值加上当前节点1作为当前节点的高度
return Math.max(getHeight(node.left), getHeight(node.right)) + 1;
}
public static void main(String[] args) {
// 构建一个高度平衡的二叉树
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(2);
root.left.left = new TreeNode(3);
root.left.right = new TreeNode(3);
root.right.left = new TreeNode(3);
root.right.right = new TreeNode(3);
BalancedBinaryTree balancedBinaryTree = new BalancedBinaryTree();
System.out.println(balancedBinaryTree.isBalanced(root)); // 输出 true
}
}
257. 二叉树的所有路径 (优先掌握递归)
这是大家第一次接触到回溯的过程, 我在视频里重点讲解了 本题为什么要有回溯,已经回溯的过程。
如果对回溯 似懂非懂,没关系, 可以先有个印象。
题目链接/文章讲解/视频讲解:https://programmercarl.com/0257.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%89%80%E6%9C%89%E8%B7%AF%E5%BE%84.html
思考:
步骤:
- 定义二叉树节点类
TreeNode
,包括值val
、左子树left
和右子树right
。 - 创建
BinaryTreePaths
类,其中包含一个binaryTreePaths
方法用于返回从根节点到叶子节点的所有路径。 - 在
binaryTreePaths
方法中,先创建一个空的路径集合paths
。 - 若根节点为空,直接返回空的路径集合。
- 使用深度优先搜索(DFS)遍历二叉树,定义一个辅助方法
dfs
,参数包括当前节点node
、当前路径path
和路径集合paths
。 - 若当前节点是叶子节点(即没有左右子树),将当前路径加入结果集。
- 若当前节点有左子树,递归调用
dfs
方法遍历左子树,并将当前节点值加入路径中。 - 若当前节点有右子树,递归调用
dfs
方法遍历右子树,并将当前节点值加入路径中。 - 在
main
方法中,构建一棵二叉树,并调用binaryTreePaths
方法获取从根节点到叶子节点的所有路径。 - 输出结果。
- 运行程序,得到结果。
注意事项:
- 需要使用深度优先搜索(DFS)遍历二叉树,递归地遍历左右子树。
- 当遍历到叶子节点时,将当前路径加入结果集。
- 路径可以使用字符串来表示,路径中的节点值之间用"->"连接。
完整代码
import java.util.ArrayList;
import java.util.List;
class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode(int val) {
this.val = val;
}
}
public class BinaryTreePaths {
public List<String> binaryTreePaths(TreeNode root) {
List<String> paths = new ArrayList<>();
if (root == null) {
return paths;
}
dfs(root, "", paths);
return paths;
}
private void dfs(TreeNode node, String path, List<String> paths) {
if (node.left == null && node.right == null) {
paths.add(path + node.val); // 当前节点是叶子节点,将路径加入结果集
return;
}
if (node.left != null) {
dfs(node.left, path + node.val + "->", paths); // 递归遍历左子树
}
if (node.right != null) {
dfs(node.right, path + node.val + "->", paths); // 递归遍历右子树
}
}
public static void main(String[] args) {
// 构建二叉树
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.right = new TreeNode(5);
BinaryTreePaths binaryTreePaths = new BinaryTreePaths();
List<String> paths = binaryTreePaths.binaryTreePaths(root);
System.out.println(paths); // 输出 ["1->2->5", "1->3"]
}
}
404.左叶子之和 (优先掌握递归)
其实本题有点文字游戏,搞清楚什么是左叶子,剩下的就是二叉树的基本操作。
题目链接/文章讲解/视频讲解:https://programmercarl.com/0404.%E5%B7%A6%E5%8F%B6%E5%AD%90%E4%B9%8B%E5%92%8C.html
思考:
步骤:
- 定义二叉树节点类
TreeNode
,包括值val
、左子树left
和右子树right
。 - 创建
SumOfLeftLeaves
类,其中包含一个sumOfLeftLeaves
方法用于返回所有左叶子之和。 - 若根节点为空,直接返回0。
- 使用深度优先搜索(DFS)遍历二叉树,定义一个辅助方法
dfs
,参数包括当前节点node
和一个表示当前节点是否为左叶子的布尔值isLeft
。 - 若当前节点是叶子节点(即没有左右子树),判断当前节点是否为左叶子,若是,则返回节点值,否则返回0。
- 初始化一个变量
sum
用于累加左叶子节点的值。 - 若当前节点有左子树,递归调用
dfs
方法遍历左子树,并将当前节点标记为左叶子。 - 若当前节点有右子树,递归调用
dfs
方法遍历右子树,并将当前节点标记为非左叶子。 - 将左子树和右子树的结果累加到
sum
中。 - 返回
sum
作为最终的左叶子之和。 - 在
main
方法中,构建一棵二叉树,并调用sumOfLeftLeaves
方法获取所有左叶子之和。 - 输出结果。
- 运行程序,得到结果。
注意事项:
- 需要使用深度优先搜索(DFS)遍历二叉树,递归地遍历左右子树。
- 在递归过程中,需要传入一个额外的参数来表示当前节点是否为左叶子。
- 当遍历到叶子节点时,判断当前节点是否为左叶子,若是则返回节点值,否则返回0。
- 将左子树和右子树的结果累加到最终的左叶子之和中。
完整代码
class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode(int val) {
this.val = val;
}
}
public class SumOfLeftLeaves {
public int sumOfLeftLeaves(TreeNode root) {
if (root == null) {
return 0;
}
return dfs(root, false); // 初始时没有左叶子,传入false
}
private int dfs(TreeNode node, boolean isLeft) {
if (node.left == null && node.right == null) {
if (isLeft) {
return node.val; // 若当前节点是左叶子,返回节点值
} else {
return 0; // 若当前节点不是左叶子,返回0
}
}
int sum = 0;
if (node.left != null) {
sum += dfs(node.left, true); // 递归遍历左子树,并标记当前节点是左叶子
}
if (node.right != null) {
sum += dfs(node.right, false); // 递归遍历右子树,并标记当前节点不是左叶子
}
return sum;
}
public static void main(String[] args) {
// 构建二叉树
TreeNode root = new TreeNode(3);
root.left = new TreeNode(9);
root.right = new TreeNode(20);
root.right.left = new TreeNode(15);
root.right.right = new TreeNode(7);
SumOfLeftLeaves sumOfLeftLeaves = new SumOfLeftLeaves();
int sum = sumOfLeftLeaves.sumOfLeftLeaves(root);
System.out.println(sum); // 输出 24
}
}