🌺The Begin🌺点点关注,收藏不迷路🌺
|
1. 题目描述
给定一个二叉搜索树(BST)和要删除的key值,删除对应的节点并保持BST性质,返回更新后的根节点。
示例
示例1:
输入: root = [5,3,6,2,4,null,7], key = 3
输出: [5,4,6,2,null,null,7]
解释: 删除节点3后,可以用节点4或节点2替代
示例2:
输入: root = [5,3,6,2,4,null,7], key = 0
输出: 原树不变(未找到key)
2. 解题思路
- 查找节点:利用BST性质定位要删除的节点
- 删除策略:
- 叶子节点:直接删除
- 单子树:用子树替代
- 双子树:用前驱或后继节点替代
- 递归处理:在子树中继续查找和删除
3. 代码实现
#include <stdlib.h>
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
};
// 找到子树中的最小值节点
struct TreeNode* findMin(struct TreeNode* node) {
while (node->left != NULL) {
node = node->left;
}
return node;
}
struct TreeNode* deleteNode(struct 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) {
// 只有右子树或无子树
struct TreeNode* temp = root->right;
free(root);
return temp;
} else if (root->right == NULL) {
// 只有左子树
struct TreeNode* temp = root->left;
free(root);
return temp;
} else {
// 有两个子节点:用右子树的最小值替代当前节点
struct TreeNode* temp = findMin(root->right);
root->val = temp->val;
root->right = deleteNode(root->right, temp->val);
}
}
return root;
}
代码注释
- findMin函数:查找子树中的最小值节点(最左节点)
- 递归删除:
- 根据key值决定搜索左/右子树
- 找到节点后分三种情况处理
- 节点替换:
- 双子树时用后继节点(右子树最小值)替代
- 保持BST性质不变
4. 复杂度分析
- 时间复杂度:O(h),h为树高,最坏情况O(n)
- 空间复杂度:O(h),递归栈空间
5. 示例解析
示例1解析
删除节点3:
1. 找到右子树最小值4
2. 用4替换3
3. 在右子树中删除原来的4节点
结果树: [5,4,6,2,null,null,7]
6. 边界情况
- 空树:直接返回NULL
- 叶子节点:直接删除
- 根节点删除:正确处理根节点替换
- 未找到key:返回原树
7. 算法优化
- 迭代实现:减少递归栈空间
- 随机选择前驱/后继:避免树不平衡
- 平衡BST删除:结合平衡树特性优化
8. 总结
这种递归删除方法:
- 保持BST性质不变
- 处理所有节点情况(0/1/2个子节点)
- 代码简洁高效
- 是BST删除操作的标准实现
展示了递归在树操作中的典型应用,是算法设计的经典范例。
🌺The End🌺点点关注,收藏不迷路🌺
|