题目描述

✅ 1325. 删除给定值的叶子节点

image-20260929000932710

image-20260929000932713

题意分析

删除值等于 target 的叶子节点,并继续删除由此新产生的目标叶子,直到不能再删。节点的值等于目标还不够,必须同时没有左右孩子;原本不是叶子的节点也可能在孩子删完后满足条件。

解法:后序遍历

核心思路

[!blue]

当前节点是否应该删除,取决于左右子树删除后的结果,所以要先处理孩子,再处理自己,也就是后序遍历。

把递归函数定义为:接收一棵子树,返回完成所有必要删除后的新根。若整棵子树被删空,就返回空。父节点必须把这个返回值写回原来的孩子位置,才能真正断开被删除的子树。

左右递归结束后,两个孩子都已经稳定。若当前节点的左右孩子均为空且值为 target,它就是应删除的叶子,返回空;否则保留当前节点并返回它。

这样一趟遍历就能完成连锁删除:孩子删空会立刻反映在父节点的判断中。被保留的节点要么值不是目标,要么仍有已经处理完成的孩子,之后不会再变成可删除的目标叶子,因此不需要从根重复扫描。

解题步骤

  1. 当前节点为空时直接返回空,表示该位置没有需要保留的子树。
  2. 递归处理左右子树,分别用返回值更新 root.left 和 root.right。
  3. 检查更新后的节点:两孩子都为空且节点值等于 target 时返回空,否则返回 root。
  4. 整棵树也使用同一个返回约定,最外层返回值就是删除后的根。

根节点同样可能被删掉,无需单独寻找它的父节点。只有一个节点时,是否返回空完全由它的值是否等于 target 决定。

代码实现

class Solution {
    public TreeNode removeLeafNodes(TreeNode root, int target) {
        if (root == null) {
            return null;
        }

        // 先接回删除后的孩子,当前节点可能因此成为新叶子
        root.left = removeLeafNodes(root.left, target);
        root.right = removeLeafNodes(root.right, target);

        // 孩子已经处理完成,此时才能判断新形成的目标叶子
        if (root.left == null && root.right == null && root.val == target) {
            return null;
        }

        return root;
    }
}
func removeLeafNodes(root *TreeNode, target int) *TreeNode {
    if root == nil {
        return nil
    }
    // 先接回删除后的孩子,当前节点可能因此成为新叶子
    root.Left = removeLeafNodes(root.Left, target)
    root.Right = removeLeafNodes(root.Right, target)
    // 孩子已经处理完成,此时才能判断新形成的目标叶子
    if root.Left == nil && root.Right == nil && root.Val == target {
        return nil
    }
    return root
}

复杂度分析

  • 时间复杂度:$O(n)$,每个节点只访问一次,删除判断为常数时间。
  • 空间复杂度:$O(h)$,递归栈深度等于树高;树退化为链时为 $O(n)$。

关键点总结

[!green]

  • 后序遍历先确定孩子的最终状态,再判断当前节点是否成为目标叶子。
  • 返回值代表保留后的子树根,返回空就表示删除,父节点必须接回这个结果。
  • 连锁删除沿同一次递归的回溯方向完成,每个节点无需反复检查。

易错点总结

[!yellow]

  • 在处理孩子之前就完成判断,会漏掉孩子删除后新形成的目标叶子。
  • 只判断节点值而不判断两个孩子是否为空,会连带删掉仍应保留的后代。
  • 只递归调用而不更新孩子链接,父节点仍会指向已经返回空的旧节点。
  • 调用者也要接住最外层返回值,否则无法得到根节点被删除后的空树。

相似题目

题目 难度 关联与区别
814. 二叉树剪枝 中等 同样后序剪枝,本题删除目标叶子后还可能产生新的目标叶子,原题删除不含1的整棵子树。
补充题 118. 二叉树的叶子父节点剪枝 中等 变形题只依据原始叶子找父节点并剪去子树,本题会继续处理新产生的目标叶子。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2023/32266343
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!