题目描述
给定一个二叉搜索树的根结点 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
算法
递归
递归处理,分为三种情况:
1.叶子结点可以立即被删除
2.具有一个儿子的结点:
3.具有两个儿子的结点:
采用该结点右子树最小的数据代替该结点的数据并递归删除那个结点
(或者找其左子树最大的数据…)
综上:
(a)当该结点为叶子结点,则让该结点的父结点指向其变为NULL,然后释放结点;
(b)当该结点不是叶子结点,但左子树或者右子树为空,则:
(1)若左子树为空,则让该结点父结点指向其右结点;
(2)若右子树为空,则让该结点父结点指向其左结点。
(c)当该结点不是叶子结点,但左子树和右子树都不为空,则:
找到该结点右子树最小的数据代替该结点的数据并删除那个结点;
或者找到该结点左子树最大的数据代替该结点的数据…。
C++ 代码
class Solution {
public:
TreeNode* find(TreeNode* root){
if(!root)
return NULL;
else if(!(root->left))
return root;
else
return find(root->left);
}
TreeNode* deleteNode(TreeNode* root, int key) {
TreeNode* temp;
if(!root)
return root;
else if(root->val>key)
root->left=deleteNode(root->left,key);
else if(root->val<key)
root->right=deleteNode(root->right,key);
else if(root->left&&root->right){
temp=find(root->right);
root->val=temp->val;
root->right=deleteNode(root->right,root->val);
}
else{
temp=root;
if(root->left==NULL)
root=root->right;
else if(root->right==NULL)
root=root->left;
delete temp;
return root;
}
return root;
}
};