问题描述
给定一棵具有不同节点值的二叉查找树,删除树中与给定值相同的节点。如果树中没有相同值的节点,就不做任何处理。你应该保证处理之后的树仍是二叉查找树。
样例
给出如下二叉查找树:
5
/ \
3 6
/ \
2 4
删除节点3之后,你可以返回:
5
/ \
2 6
\
4
或者:
5
/ \
4 6
/
2
递归解法
首先判断根节点是否为空。根据二叉查找树的性质,我们可以快速定位到要删除的节点,我们对于当前节点值不等于key的情况,根据大小关系对其左右子节点分别调用递归函数。
若当前节点就是要删除的节点,我们首先判断是否有一个子节点不存在。如果它有一个子节点不存在,那么我们就让其父节点指向另一个节点。难点就在于处理左右子节点都存在的情况,我们需要在右子树找到最小值,即右子树中最左下方的节点,然后将该最小值赋值给当前节点,然后再在右子树中调用递归函数来删除这个值最小的节点。
class Solution {
public:
/**
* @param root: The root of the binary search tree.
* @param value: Remove the node with given value.
* @return: The root of the binary search tree after removal.
*/
TreeNode* del(TreeNode* cur) {
if(root==NULL) return NULL;
if(root->val > value) {
root->left = removeNode(root->left, value);
} else if (root->val < value) {
root->right = removeNode(root->right, value);
} else {
if (root->left==NULL || root->right == NULL) {
return root->left==NULL ? root->right : root->left;
} else {
TreeNode* cur = root->right;
while(cur->left!=NULL) cur= cur->left;
root->val = cur->val;
root->right = removeNode(root->right, cur->val);
}
}
return root;
}
};
非递归解法
通过二叉查找树,快速定位要删除的节点,如果没找到直接返回空。遍历的过程要记录上一个位置的节点pre。
如果pre不存在,说明要删除的是根节点;如果要删除的节点在pre的左子树中,那么pre的左子节点连上删除后的节点,反之pre的右子节点连上删除后的节点。
在删除函数中,如果左右子节点都不存在,那么返回空;如果有一个不存在,那么我们返回那个存在的;
难点还是在于处理左右子节点都存在的情况,还是要找到需要删除节点的右子树中的最小值,然后把最小值赋值给要删除节点,然后就是要处理最小值可能存在的右子树的连接问题。
如果要删除节点的右子节点没有左子节点了的话,那么最小值的右子树直接连到要删除节点的右子节点上即可(因为此时原本要删除的节点的值已经被最小值替换了,所以现在其实是要删掉最小值节点)。
否则我们就把最小值节点的右子树连到其父节点的左子节点上。
class Solution {
public:
/**
* @param root: The root of the binary search tree.
* @param value: Remove the node with given value.
* @return: The root of the binary search tree after removal.
*/
TreeNode* del(TreeNode* cur) {
if(cur->left == NULL || cur->right == NULL){
return cur->left == NULL ? cur->right : cur->left;
}
TreeNode* pre = cur, *node = cur->right;
while (node->left) {
pre = node;
node = node->left;
}
cur->val = node->val;
if (pre == cur)
cur->right = node->right;
else
pre->left = node->right;
return cur;
}
TreeNode* removeNode(TreeNode* root, int value) {
// write your code here
TreeNode* pre = NULL, *cur = root;
while(cur) {
if (cur->val == value)
break;
pre = cur;
if (cur->val > value){
cur = cur->left;
} else {
cur = cur->right;
}
}
if(cur==NULL) return root;
if(pre==NULL) return del(cur);
if(pre->left && pre->left->val == value) {
pre->left = del(cur);
} else {
pre->right = del(cur);
}
return root;
}
};