二叉树的边界
难度:
标签:
题目描述
代码结果
运行时间: 27 ms, 内存: 17.5 MB
/*
* 题目思路:
* 1. 使用流处理来实现二叉树的边界遍历。
* 2. 找到左边界、叶子节点、右边界,并合并成结果。
*/
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public class BoundaryOfBinaryTreeStream {
public List<Integer> boundaryOfBinaryTree(TreeNode root) {
if (root == null) return Collections.emptyList();
List<Integer> leftBoundary = new ArrayList<>();
List<Integer> rightBoundary = new ArrayList<>();
List<Integer> leaves = new ArrayList<>();
if (!isLeaf(root)) leftBoundary.add(root.val);
collectLeftBoundary(root.left, leftBoundary);
collectLeaves(root, leaves);
collectRightBoundary(root.right, rightBoundary);
Collections.reverse(rightBoundary);
return Stream.of(leftBoundary, leaves, rightBoundary)
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
private void collectLeftBoundary(TreeNode node, List<Integer> res) {
while (node != null) {
if (!isLeaf(node)) res.add(node.val);
if (node.left != null) node = node.left;
else node = node.right;
}
}
private void collectLeaves(TreeNode node, List<Integer> res) {
if (isLeaf(node)) {
res.add(node.val);
return;
}
if (node.left != null) collectLeaves(node.left, res);
if (node.right != null) collectLeaves(node.right, res);
}
private void collectRightBoundary(TreeNode node, List<Integer> res) {
while (node != null) {
if (!isLeaf(node)) res.add(node.val);
if (node.right != null) node = node.right;
else node = node.left;
}
}
private boolean isLeaf(TreeNode node) {
return node.left == null && node.right == null;
}
}
解释
方法:
这个题目可以通过深度优先搜索(DFS)来解决。解题思路如下:
1. 先将根节点的值加入结果列表。
2. 通过先序遍历(preorder)得到左边界节点的值,并加入结果列表。注意要排除叶子节点。
3. 通过DFS找到所有叶子节点的值,按从左到右的顺序加入结果列表。
4. 通过后序遍历(postorder)得到右边界节点的值,并以逆序的方式加入结果列表。注意要排除叶子节点。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
在定义左边界和右边界的节点时,为什么选择排除叶子节点而不是包括它们在内?
▷🦆
在进行左边界的先序遍历时,如果遇到一个节点既没有左子树也没有右子树时,函数直接返回,这是否意味着可能会漏掉一些边界条件?
▷🦆
当根节点只有一侧子树(例如只有左子树或只有右子树)时,这种情况下的边界处理逻辑是否有所不同?
▷🦆
在递归函数`leftBoundary`和`rightBoundary`中,如果节点的左或右子树为null,你选择遍历另一侧子树。这种选择是否可能影响到最终边界的正确性?
▷