纠正二叉树
难度:
标签:
题目描述
代码结果
运行时间: 87 ms, 内存: 21.4 MB
/*
题目思路:
由于Java Stream API不适合直接操作和修改数据结构,因此我们在这里仍然使用经典的遍历方法。
使用Stream API的部分是为了展示我们如何使用它来进行一些集合操作,例如过滤和查找。
我们通过遍历树,记录看到的节点,并处理发现的误入节点。
*/
public class Solution {
public TreeNode correctBinaryTree(TreeNode root) {
Set<TreeNode> seen = new HashSet<>();
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
Stream.of(node.right, node.left).filter(Objects::nonNull).forEach(child -> {
if (seen.contains(child)) {
return null;
}
queue.add(child);
});
seen.add(node);
}
return root;
}
}
/*
假设树节点类如下:
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
*/
解释
方法:
该题解采用了深度优先搜索(DFS)的方法来解决问题。首先,定义了一个集合 `visited_nodes` 用以记录访问过的节点。在递归函数 `dfs` 中,如果当前节点为空或者当前节点的右子节点已经在 `visited_nodes` 中(即被访问过),则说明存在非法引用,此节点应被删除,返回 `None`。否则,将当前节点添加到 `visited_nodes`,递归处理右子节点和左子节点。通过这种方式,算法从根节点开始,逐层向下检查并剪枝,从而修复二叉树。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
在题解中使用 `visited_nodes` 集合来记录节点,为什么选择集合而不是列表或其他数据结构?
▷🦆
题解中递归删除节点的逻辑是如何确保不会错误删除未被非法引用的有效节点的?
▷🦆
在处理二叉树的右子节点之前就将当前节点添加到 `visited_nodes`,这种顺序对算法的正确性和效率有何影响?
▷🦆
题解提到当节点的右子节点已经在 `visited_nodes` 中时,就删除该节点。如何处理这种情况下的左子节点,它们是否也需要特别处理?
▷