OCI SWE · VO Coding

Oracle OCI:删除值为 Target 的叶节点与连锁父节点

从 Oracle VO 的删除目标叶节点题出发,用后序遍历一次处理孩子删除后新形成的目标叶。

题目重点:从 Oracle VO 的删除目标叶节点题出发,用后序遍历一次处理孩子删除后新形成的目标叶。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 二叉树节点带 value、left、right;输入 target 是目标值,可修改树指针并返回新根。
  • 只删除 value==target 且当前无孩子的节点;如果孩子删完使父节点成为目标叶,也继续删除。若面试官仅要求原始叶一次性删除,需改变口径。

解题路线

  1. 递归先处理左子树与右子树,并把可能为空的新根写回当前节点;这保证检查当前节点时,两侧孩子已经按规则处理。
  2. 若当前左右都为空且值为 target,返回 None;否则返回当前节点。根节点本身被删除时整个返回值为 None。
  3. 正确性按树高归纳:叶节点判断直接正确;假设两个更矮子树处理正确,父节点看到的孩子状态就是所有后续删除的最终状态,因此可准确决定是否删除。
  4. 迭代版本可用显式后序栈以避免极深树递归栈溢出,但要记录父指针和访问阶段。

手动走一遍

根 1,左孩子 2,左孩子的左孩子 2:最下层 2 先删;上一层 2 变成叶后也删;根 1 保留。若根值也是 2,整棵链都会删除。

Python 参考实现

下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。

代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。

"""Delete target-valued leaves, including parents exposed by earlier deletion."""


class TreeNode:
    def __init__(
        self,
        value: int,
        left: "TreeNode | None" = None,
        right: "TreeNode | None" = None,
    ):
        self.value = value
        self.left = left
        self.right = right


def remove_target_leaves(root: TreeNode | None, target: int) -> TreeNode | None:
    if root is None:
        return None
    root.left = remove_target_leaves(root.left, target)
    root.right = remove_target_leaves(root.right, target)
    if root.left is None and root.right is None and root.value == target:
        return None
    return root

复杂度

N 个节点各访问一次,O(N) 时间;递归额外栈 O(H),H 为树高,最坏 O(N),平衡树 O(log N)。原地更新指针,不计调用栈之外的额外空间。

易错点与追问

容易失分的边界

  • 先检查并删除父节点再递归,漏掉删除孩子后才形成的新叶。
  • 只遍历一轮原始叶,连锁层数多时结果不完整。
  • 不返回新根,导致原根被删时调用者仍持有旧引用。

继续深挖

  • 如果只删原始叶而不连锁,如何标记初始树中的叶并处理?
  • 若树很深不允许递归,如何用显式后序遍历保证删除顺序?
✓已复制微信号!