给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
- 首先找到需要删除的节点;
- 如果找到了,删除它。
说明: 要求算法时间复杂度为 O(h),h 为树的高度。
示例:
root = [5,3,6,2,4,null,7] key = 3 5 / \ 3 6 / \ \ 2 4 7 给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。 一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。 5 / \ 4 6 / \ 2 7 另一个正确答案是 [5,2,6,null,4,null,7]。 5 / \ 2 6 \ \ 4 7
经典的删除算法,首先用递归的方法找到要删除的节点,对于删除的节点没有左右子树的情况是很容易的,如果 既有左子树又有右子树,那么从右子数找一个最小值,或左子树找一个最大值,把它的数值给当前节点,然后再左子数和右子数中删除相应节点即可。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* FindMin(TreeNode* root){
if(root){
while(root->left)
root = root->left;
}
return root;
}
TreeNode* deleteNode(TreeNode* root, int key) {
TreeNode* temp;
if(!root)
return root;
else 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 && root->right){
temp = FindMin(root->right); // 在右子数中找最小值
root->val = temp->val; // 换值即可,不用动节点
root->right = deleteNode(root->right,root->val); // 在右子数中删除新的元素
}
// 被删除节点没有左儿子或右儿子
else{
temp = root;
if(!root->left)
root=root->right;
else if(!root->right)
root=root->left;
delete temp;
}
}
return root;
}
};