解题思路
逻辑:首先找到要删除的结点;找到后分情况讨论:
(1)左右孩子都为空,直接删除结点(delete node)
(2)左孩子为空,右孩子不为空,删除结点,右孩子补位
(3)右孩子为空,左孩子不为空,删除结点,左孩子补位
(4)左右孩子都不为空,就将左孩子连接到右孩子最左边的叶子结点上,然后删除结点,将右孩子补位
1、递归法:
(1)确定递归终止条件:当本次递归没找到要删除的结点时,返回空
(2)单层递归逻辑:根据要找的结点值与当前传入递归结点进行比较,确定搜索方向。注意用root->left root->right来承接递归返回值。当递归找到要删除的结点后,根据上述4个情况,返回相应的结点。
(3)返回值:root根结点
class Solution {
public:
TreeNode* deleteNode(TreeNode* root, int key) {
if(!root)return nullptr;//遇到空结点,说明没有找到要删除的结点,则返回空
if(root->val == key ){
//1、找到了删除结点,其左右孩子均为空
if(!root->left && !root->right) {
delete root;
return nullptr;
}
//2、找到了删除结点,其左孩子为空,右孩子不为空
else if(!root->left){
TreeNode* cur=root->right;
delete root;
return cur;
}
//2、找到了删除结点,其右孩子为空,左孩子不为空
else if(!root->right){
TreeNode*cur=root->left;
delete root;
return cur;
}
//1、找到了删除结点,其左右孩子均不为空
else{
TreeNode* rightnode=root->right;
TreeNode* cur=rightnode;
while(rightnode->left){
rightnode=rightnode->left;
}
rightnode->left=root->left;
delete root;
return cur;
}
}
if(root->val>key)root->left=deleteNode(root->left,key);
if(root->val<key)root->right=deleteNode(root->right,key);
return root;
}
};
2、迭代法
利用双指针思想,cur指向要删除点,pre指向要删除点的父结点。
class Solution {
public:
//删除结点的函数
TreeNode* deleteOneNode(TreeNode* node){
if(!node)return nullptr;
if(!node->right)return node->left;
TreeNode* p=node->right;
TreeNode* tmp=node;
while(p->left){
p=p->left;
}
p->left=node->left;
node=node->right;
delete tmp;
return node;
}
TreeNode* deleteNode(TreeNode* root, int key) {
//迭代法
if(!root)return nullptr;
TreeNode* cur=root;
TreeNode* pre=nullptr;
//找到要删除的结点
while(cur){
if(cur->val == key)break;
pre=cur;//更新pre
if(cur->val > key)cur=cur->left;
else if(cur->val < key)cur=cur->right;
}
//如果pre为空,说明指针没动,根结点就是要删除的点
if(pre==nullptr)return deleteOneNode(cur);
//根据二叉搜索树的特点确定搜索方向
if(pre->left && pre->left->val == key){
pre->left=deleteOneNode(cur);
}
if(pre->right && pre->right->val == key){
pre->right=deleteOneNode(cur);
}
return root;
}
};