Java练习:如何从树节点数组中删除指定值为根的对应子树
问题解答
思路正确性确认
你的思路完全可行,用临时集合筛选需要保留的节点最后再转回数组的方案,避开了原地修改数组的复杂度,逻辑清晰且不易出错。
具体实现步骤
你只需要先完成「收集所有待删除节点ID」的前置步骤,再过滤原数组即可,核心逻辑如下:
- 首先确认节点结构(题目已提供可直接跳过)
class TreeNode { // 节点自身唯一ID int id; // 父节点ID,根节点的parentId通常约定为-1或0,以题目规则为准 int parentId; // 题目给定的节点值 int value; // 构造方法、getter/setter省略 }
- 实现删除逻辑,推荐用
HashSet存储待删除ID,查询时间复杂度为O(1),结合BFS遍历所有后代节点:
public TreeNode[] deleteSubtree(TreeNode[] nodes, int targetValue) { Set<Integer> toDeleteIds = new HashSet<>(); Queue<Integer> queue = new LinkedList<>(); // 第一步:找到待删除的子树根节点 for (TreeNode node : nodes) { if (node.value == targetValue) { toDeleteIds.add(node.id); queue.add(node.id); // 如果题目允许节点值重复,删除本行break即可 break; } } // 第二步:BFS遍历所有后代,加入待删除集合 while (!queue.isEmpty()) { Integer currentParentId = queue.poll(); for (TreeNode node : nodes) { if (node.parentId == currentParentId && !toDeleteIds.contains(node.id)) { toDeleteIds.add(node.id); queue.add(node.id); } } } // 第三步:过滤保留节点,转数组返回 List<TreeNode> retainNodes = new ArrayList<>(); for (TreeNode node : nodes) { if (!toDeleteIds.contains(node.id)) { retainNodes.add(node); } } return retainNodes.toArray(new TreeNode[0]); }
逻辑说明
后代节点的判定逻辑非常直接:子节点的parentId一定等于它直接父节点的id,只要父节点在待删除集合中,对应的子节点也属于待删除范围,通过BFS就能逐层把所有子孙后代全部识别出来。
如果处理的节点量级很大,可以提前遍历一次数组构建Map<Integer, List<TreeNode>> parentIdToChildren的映射,把相同parentId的节点提前归类,查找子节点时不需要每次遍历全数组,效率更高。
如果不存在值等于targetValue的节点,待删除集合为空,方法会直接返回原数组所有元素,符合预期。
内容的提问来源于stack exchange,提问作者Hboss62
相关产品推荐
相关产品推荐

