删点成林-LeetCode
1110. 删点成林 - Delete Nodes And Return Forest
🎯 问题描述(来源于LeetCode)
描述:
给定二叉树的根节点 root,以及一个要删除的节点值列表 to_delete。
删除所有值为 to_delete 中的节点后,剩下的节点会形成若干棵不相交的子树(森林)。
返回森林中所有子树的根节点列表(顺序任意)。
说明:
- 删除一个节点会将其左右子树断开,分别成为新的树。
- 被删除的节点本身不保留。
- 森林中每棵树的根节点是原树中未被删除且父节点被删除(或原根节点)的节点。
示例:
- 示例 1:
1 | 输入: root = [1,2,3,4,5,6,7], to_delete = [3,5] |
- 示例 2:
1 | 输入: root = [1,2,4,null,3], to_delete = [3] |
💻 解题思路
思路1:DFS + 传递父节点删除状态
算法步骤
-
将待删除列表转为集合
to_del以提高查找效率。 -
定义递归函数
dfs(node, parent_deleted):- 参数
node:当前遍历的节点。 - 参数
parent_deleted:布尔值,表示父节点是否被删除。 - 返回值:处理后的当前节点(若当前节点被删除则返回
None,否则返回节点本身)。
- 参数
-
递归终止:若
node为None,返回None。 -
判断当前节点是否被删除:
cur_deleted = node.val in to_del。 -
判断是否加入森林:
- 如果父节点被删除(
parent_deleted == True)且当前节点不被删除(cur_deleted == False),则当前节点成为新树的根,将其加入结果列表res。
- 如果父节点被删除(
-
递归处理左右子树:
node.left = dfs(node.left, cur_deleted)node.right = dfs(node.right, cur_deleted)
将当前节点的删除状态传递给子节点。
-
返回值:
- 若当前节点被删除,返回
None,否则返回当前节点(其左右子节点已更新)。
- 若当前节点被删除,返回
-
启动递归:从根节点开始,初始父节点视为被删除(
parent_deleted = True),因为根节点没有父节点,相当于其父节点被删除,这样如果根节点不被删除,它会自动加入森林。
思路1:代码实现
1 | # Definition for a binary tree node. |
思路1:📊 性能分析
- 时间复杂度:,每个节点访问一次,集合查找 。
- 空间复杂度:,递归栈深度为树高 ,结果列表存储最多 个根节点,总体 。
思考
- 本题的关键是自顶向下传递父节点删除状态,并根据该状态决定当前节点是否成为新树的根。
- 利用后序遍历断开子节点连接:当前节点可能被删除,但其子节点仍需要继续处理,因此先递归再更新指针。
- 也可以使用 BFS 层序遍历,但 DFS 更简洁。
- 注意:
parent_deleted初值为True,确保根节点若不被删除,会被加入结果集。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 笺札!






