给定一个二叉搜索树的根节点 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
思路:
第一次刷LeetCode,感觉吼吼玩呀
删除操作(删除的是z结点)
(1)若z是叶子结点,直接删掉
(2)若z只有一棵左子树,或一棵右子树,删除后,把子树提上来
(3)若z有左、右子树
则找到z节点的右子树的最左的节点,把它替换删除结点。(若z结点右子树无左结点,则用其右子树根节点代替)
代码如下:
/**
* 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* deleteNode(TreeNode* root, int key) {
if(root==NULL){
return NULL;
}
if(key<root->val){//被删除结点在左子树中
root->left=deleteNode(root->left,key);
return root;
}
else if(key>root->val){//被删除结点在右子树中
root->right=deleteNode(root->right,key);
return root;
}
else{//该点为被删除节点
if(root->left==NULL){//左子树为空
return root->right;
}
else if(root->right==NULL){//右子树为空
return root->left;
}
else{//左右子树都不为空,返回右子树的最左结点作为新根节点
TreeNode *p=Min(root->right);
p->right=deleteMin(root->right);
p->left=root->left;
return p;
}
}
}
TreeNode* Min(TreeNode* node){//找到结点node的最左结点
if(node->left==NULL){
return node;
}
return Min(node->left);
}
TreeNode* deleteMin(TreeNode* node){//删除node子树上最左的节点,并返回node的右结点
if(node->left==NULL){//没有左结点,则直接返回右结点
return node->right;
}
node->left=deleteMin(node->left);
return node;
}
};