删点成林

73 阅读3分钟

🎈算法并不一定都是很难的题目,也有很多只是一些代码技巧,多进行一些算法题目的练习,可以帮助我们开阔解题思路,提升我们的逻辑思维能力,也可以将一些算法思维结合到业务代码的编写思考中。简而言之,平时进行的算法习题练习带给我们的好处一定是不少的,所以让我们一起来养成算法练习的习惯。今天练习的题目是一道比较简单的题目 ->删点成林

问题描述

给出二叉树的根节点 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 <= 1000
  • to_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,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,在此谢谢大家的支持,我们下文再见 🙌。