算法日记day 18(二叉树的所有路径|左叶子之和)
一、二叉树的所有路径
题目:
给你一个二叉树的根节点 root
,按 任意顺序 ,返回所有从根节点到叶子节点的路径。
叶子节点 是指没有子节点的节点。
示例 1:
输入:root = [1,2,3,null,5] 输出:["1->2->5","1->3"]
示例 2:
输入:root = [1] 输出:["1"]
思路:
采用前序遍历,递归和回溯法相辅相成, 用一个列表负责记录所走的路径,从根节点开始对每个节点依次遍历,直到遇到左右子节点均为空为止(即叶子节点),结束遍历,同时记录该条路径上所有的节点,并用"->"拼接
代码:
public void traversal(TreeNode root, List<Integer> paths, List<String> res) {
paths.add(root.val); // 将当前节点的值添加到路径列表中
// 如果当前节点是叶子节点,将路径列表转换为字符串并加入结果列表
if (root.left == null && root.right == null) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < paths.size() - 1; i++) {
sb.append(paths.get(i)).append("->");
}
sb.append(paths.get(paths.size() - 1));
res.add(sb.toString());
return;
}
// 递归处理左子树
if (root.left != null) {
traversal(root.left, paths, res);
paths.remove(paths.size() - 1); // 回溯,移除左子树的路径节点
}
// 递归处理右子树
if (root.right != null) {
traversal(root.right, paths, res);
paths.remove(paths.size() - 1); // 回溯,移除右子树的路径节点
}
}
- 功能:递归地遍历二叉树,并在叶子节点处将路径转换为字符串后存入结果列表。
- 逻辑:
- 将当前节点的值
root.val
添加到路径列表paths
中。 - 如果当前节点是叶子节点(即左右子节点都为
null
),将路径列表中的节点值按路径格式拼接为字符串,并添加到结果列表res
中。 - 递归处理左子树和右子树,同时在递归完成后进行回溯,即移除路径列表
paths
的最后一个节点,以便处理下一个分支的路径。
- 将当前节点的值
public List<String> binaryTreePaths(TreeNode root) {
List<String> res = new ArrayList<>();
List<Integer> paths = new ArrayList<>();
if (root == null) {
return res;
}
traversal(root, paths, res);
return res;
}
- 功能:初始化结果列表
res
和路径列表paths
,然后调用traversal
方法进行遍历。 - 逻辑:
- 如果
root
为null
,直接返回空的结果列表res
。 - 否则,调用
traversal
方法进行遍历,将结果存入res
中。
- 如果
二、左叶子之和
题目:
给定二叉树的根节点 root
,返回所有左叶子之和。
示例 1:
输入: root = [3,9,20,null,null,15,7] 输出: 24 解释: 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24
示例 2:
输入: root = [1] 输出: 0
思路:
由于在遍历到叶子节点时并不清楚其是否为左叶子节点,因此在遍历时需要判断其父节点,如果其父节点有左子节点,且该左子节点是叶子节点,则将该左子节点的值加入最终结果,然后继续遍历下一个节点
代码:
//递归法
public int sumOfLeftLeaves(TreeNode root) {
if (root == null) {
return 0;
}
// 递归计算左子树中左叶子节点的和
int leftNum = sumOfLeftLeaves(root.left);
// 递归计算右子树中左叶子节点的和
int rightNum = sumOfLeftLeaves(root.right);
int count = 0;
// 如果当前节点的左孩子存在,并且左孩子是叶子节点(即没有左右孩子)
if (root.left != null && root.left.left == null && root.left.right == null) {
count = root.left.val; // 将左叶子节点的值加入到计数中
}
// 返回当前子树中左叶子节点值之和
return leftNum + rightNum + count;
}
-
递归基础情况:
- 如果
root
为null
,即空节点,则直接返回0
,表示没有左叶子节点。
- 如果
-
递归计算:
leftNum
表示递归计算左子树中左叶子节点值之和。rightNum
表示递归计算右子树中左叶子节点值之和。
-
判断左叶子节点:
- 在当前节点
root
的左孩子存在,并且左孩子的左右孩子都为null
,即左孩子是叶子节点。 - 如果满足条件,将左孩子节点的值
root.left.val
加入到count
中。
- 在当前节点
-
返回结果:
- 返回当前子树中所有左叶子节点的值之和,即
leftNum + rightNum + count
。
- 返回当前子树中所有左叶子节点的值之和,即
//迭代法
public int sumOfLeftLeaves(TreeNode root) {
if (root == null) return 0;
Stack<TreeNode> stack = new Stack<> ();
stack.add(root); // 将根节点压入栈
int result = 0;
while (!stack.isEmpty()) {
TreeNode node = stack.pop(); // 弹出栈顶节点
// 如果当前节点的左孩子存在,并且左孩子是叶子节点(即没有左右孩子)
if (node.left != null && node.left.left == null && node.left.right == null) {
result += node.left.val; // 将左叶子节点的值加入到结果中
}
// 先压入右孩子,再压入左孩子,保证左孩子先被处理(因为栈是先入后出)
if (node.right != null) {
stack.add(node.right);
}
if (node.left != null) {
stack.add(node.left);
}
}
return result;
}
-
初始处理:
- 如果
root
为null
,直接返回0
。
- 如果
-
使用栈迭代:
- 创建一个
Stack<TreeNode>
类型的栈,并将根节点root
压入栈中。
- 创建一个
-
迭代过程:
- 在循环中,弹出栈顶的节点
node
。 - 如果
node
的左孩子存在,并且是叶子节点(即左右孩子都为null
),则将左孩子节点的值加入到result
中。
- 在循环中,弹出栈顶的节点
-
节点处理顺序:
- 因为栈是后进先出的数据结构,所以先将右孩子压入栈,再将左孩子压入栈,这样可以保证在处理时左孩子先被处理。
-
返回结果:
- 循环结束后,返回
result
,即为二叉树中所有左叶子节点值之和。
- 循环结束后,返回
今天的学习就到这里
原文地址:https://blog.csdn.net/m0_74980681/article/details/140638050
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!