🎈算法并不一定都是很难的题目,也有很多只是一些代码技巧,多进行一些算法题目的练习,可以帮助我们开阔解题思路,提升我们的逻辑思维能力,也可以将一些算法思维结合到业务代码的编写思考中。简而言之,平时进行的算法习题练习带给我们的好处一定是不少的,所以让我们一起来养成算法练习的习惯。今天练习的题目是一道比较简单的题目 ->删点成林
问题描述
给出二叉树的根节点 root,树上每个节点都有一个不同的值。
如果节点值在 to_delete 中出现,我们就把该节点从树上删去,最后得到一个森林(一些不相交的树构成的集合)。
返回森林中的每棵树。你可以按任意顺序组织答案。
示例 1:
输入: root = [1,2,3,4,5,6,7], to_delete = [3,5]
输出: [[1,2,null,4],[6],[7]]
示例 2:
输入: root = [1,2,4,null,3], to_delete = [3]
输出: [[1,2,4]]
提示:
- 树中的节点数最大为
1000。 - 每个节点都有一个介于
1到1000之间的值,且各不相同。 to_delete.length <= 1000to_delete包含一些从1到1000、各不相同的值。
思路分析
在平时写代码的过程中,我们对树形结构的数据处理可能会比较少,今天让我们通过这道题目来加深对二叉树的理解吧!首先我们应该要先理解一下题目意思,题目会给我们两个参数,分别是:
root:原始二叉树根节点;to_delete:需要删除的节点值。
我们需要遍历这棵二叉树,如果二叉树节点值出现在to_delete中的话,我们则需要将这个节点删除,删除该节点后,我们将会将该节点的子树与原来的二叉树分离开来,得到两棵新的数,所以最后我们会得到一个森林(一些不相交的树构成的集合),我们需要返回这个森林的集合。
我们可以分为以下两个步骤来进行解题:
- 1、遍历二叉树
遍历二叉树的方法有很多,我们可以选择自己喜欢的遍历方式来进行遍历,这里我选择递归前序遍历的方法来遍历这棵二叉树,简单的前序遍历代码如下:
const dfs = (r, f = "") => {
if (!r) return;
dfs(r.left, r.val);
dfs(r.right, r.val);
}
- 2、判断节点是否需要删除
遍历过程中我们需要判断当前节点是否需要删除,根据题目所说,我们只需要判断to_delete是否包含当前遍历到的节点即可,这里我们需要将节点删除,所以我们不能直接判断当前节点的值,我们应该要判断要遍历的下一个节点的值,这样可以直接通过断开连接的方式将下一个节点删除。
if (r.left && to_delete.includes(r.left.val)) {
dfs(r.left);
r.left = null;
}
if (r.right && to_delete.includes(r.right.val)) {
dfs(r.right);
r.right = null;
}
删除节点之后,我们还需要将新树保存起来,所以我们要分析一下新树根节点需要满足的条件:
- 1、父节点的节点值包含在
to_delete中或当前节点没有父节点;
f == "" || to_delete.includes(f)
- 2、当前节点值不包含于
to_delete中。
!to_delete.includes(r.val)
我们使用一个列表来保存遍历过程中发现的新树,每遍历到一个节点时需要先判断其是否为新树的根节点:
if ((f == "" || to_delete.includes(f)) && !to_delete.includes(r.val)) {
list.push(r);
}
AC代码
完整AC代码如下:
/**
* 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) {
const list = [];
const dfs = (r, f = "") => {
if (!r) return;
if ((f == "" || to_delete.includes(f)) && !to_delete.includes(r.val)) {
list.push(r);
}
if (r.left && to_delete.includes(r.left.val)) {
dfs(r.left);
r.left = null;
}
if (r.right && to_delete.includes(r.right.val)) {
dfs(r.right);
r.right = null;
}
dfs(r.left, r.val);
dfs(r.right, r.val);
};
dfs(root);
return list;
};
说在后面
🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,在此谢谢大家的支持,我们下文再见 🙌。