题目
题目来源:力扣(LeetCode)
给出二叉树的根节点 root,树上每个节点都有一个不同的值。
如果节点值在 to_delete 中出现,我们就把该节点从树上删去,最后得到一个森林(一些不相交的树构成的集合)。
返回森林中的每棵树。你可以按任意顺序组织答案。
示例:
输入:root = [1,2,3,4,5,6,7], to_delete = [3,5]
输出:[[1,2,null,4],[6],[7]]
思路分析
使用前序遍历递归遍历各个节点,然后判断节点值是否是需要删除的值,如果是,就将该节点删除,然后判断子节点是否为要删除的值,如果不是则将子节点加入结果集中。
具体地:
- 首先判断根节点是否是需要删除的值,如果不是,则将根节点加入结果集中
- 然后递归遍历所有节点,判断当前节点是否是需要删除的值:
- 如果是,则需要将该节点的 不是要删除的子节点 加入结果集中
- 递归处理左子树和右子树
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @param {number[]} to_delete
* @return {TreeNode[]}
*/
var delNodes = function (root, to_delete) {
let result = [];
// 使用 set 集合存储需要删除节点值,便于快速找到需要删除的节点
let needDelete = new Set(to_delete);
// 首先判断根节点是否需要删除,如果不需要删除,则将其加入结果集中
if (!needDelete.has(root.val)) {
result.push(root);
}
tools(root, needDelete, { left: root });
return result;
function tools(node, needDelete, p) {
// 递归退出条件
if (!node) return;
// 判断当前节点是否需要删除,如果当前节点需要删除,则需要判断是否有孩子节点
if (needDelete.has(node.val)) {
// 有左子节点并且左子节点不需要删除,则将当前节点的左子树加入结果集
node.left && !needDelete.has(node.left.val) && result.push(node.left)
// 有右子节点并且右子节点不需要删除,则将当前节点的右子树加入结果集
node.right && !needDelete.has(node.right.val) && result.push(node.right);
}
// 递归左右子树
node.left && tools(node.left, needDelete, node);
node.right && tools(node.right, needDelete, node);
// 当前删除的节点是某个父节点的节点,则需要将该父节点的左子节点或右子节点置为 null
if (needDelete.has(node.val)) {
node === p.left ? p.left = null : p.right = null;
}
}
};