LeetCode算法题(Go语言实现)_42

题目

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。

删除步骤:

  1. 首先找到需要删除的节点
  2. 如果找到了,删除它

一、代码实现


func deleteNode(root *TreeNode, key int) *TreeNode {
    if root == nil {
        return nil
    }
    
    if key < root.Val {
        root.Left = deleteNode(root.Left, key)
    } else if key > root.Val {
        root.Right = deleteNode(root.Right, key)
    } else {
        // 情况1:无子节点或只有一个子节点
        if root.Left == nil {
            return root.Right
        }
        if root.Right == nil {
            return root.Left
        }
        
        // 情况2:有两个子节点
        // 找到右子树的最小节点
        minNode := findMin(root.Right)
        // 用最小节点的值替换当前节点
        root.Val = minNode.Val
        // 删除右子树中的最小节点
        root.Right = deleteNode(root.Right, minNode.Val)
    }
    return root
}

func findMin(node *TreeNode) *TreeNode {
    for node.Left != nil {
        node = node.Left
    }
    return node
}

二、算法分析

1. 核心思路
  • 递归查找:利用BST性质递归定位目标节点
  • 三种删除情况
    1. 无子节点:直接删除
    2. 单子节点:用子节点替代
    3. 双子节点:用后继节点值替换后删除后继节点
2. 关键步骤
  1. 递归定位:根据key值大小选择左/右子树
  2. 节点替换:用后继节点(右子树最小节点)替换被删节点
  3. 递归删除:在右子树中删除后继节点
3. 复杂度
指标 说明
时间复杂度 O(h) h为树高,最坏情况O(n)
空间复杂度 O(h) 递归栈深度,最坏情况O(n)

三、图解示例

LeetCode算法题(Go语言实现)_42_第1张图片

四、边界条件与扩展

1. 特殊场景验证
  • 空树:返回nil
  • 删除根节点:正确处理根节点替换
  • 删除叶子节点:直接置为nil
  • 重复值:仅删除第一个匹配节点
2. 多语言实现
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def deleteNode(self, root: TreeNode, key: int) -> TreeNode:
        if not root:
            return None
            
        if key < root.val:
            root.left = self.deleteNode(root.left, key)
        elif key > root.val:
            root.right = self.deleteNode(root.right, key)
        else:
            if not root.left:
                return root.right
            if not root.right:
                return root.left
                
            min_node = self.findMin(root.right)
            root.val = min_node.val
            root.right = self.deleteNode(root.right, min_node.val)
        return root
    
    def findMin(self, node):
        while node.left:
            node = node.left
        return node
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

class Solution {
    public TreeNode deleteNode(TreeNode root, int key) {
        if (root == null) return null;
        
        if (key < root.val) {
            root.left = deleteNode(root.left, key);
        } else if (key > root.val) {
            root.right = deleteNode(root.right, key);
        } else {
            if (root.left == null) return root.right;
            if (root.right == null) return root.left;
            
            TreeNode minNode = findMin(root.right);
            root.val = minNode.val;
            root.right = deleteNode(root.right, minNode.val);
        }
        return root;
    }
    
    private TreeNode findMin(TreeNode node) {
        while (node.left != null) {
            node = node.left;
        }
        return node;
    }
}

五、总结与扩展

1. 核心创新点
  • 后继节点替换:保持BST性质的关键操作
  • 递归统一处理:简化三种删除情况的代码实现
2. 扩展应用
  • 批量删除:支持删除多个匹配节点
  • 前驱节点替代:可用左子树最大节点替代被删节点
  • 平衡删除:结合平衡树旋转操作
3. 工程优化
  • 迭代实现:减少递归带来的栈空间消耗
  • 父节点指针:加速节点定位和替换操作
  • 内存回收:显式释放被删节点内存

你可能感兴趣的:(LeetCode,算法,leetcode,golang)