LeetCode450. 删除二叉搜索树中的节点-迭代与递归解法(含java与c++代码)
作者:互联网
https://leetcode-cn.com/problems/delete-node-in-a-bst/
题意
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
首先找到需要删除的节点;
如果找到了,删除它。
说明: 要求算法时间复杂度为 O(h),h 为树的高度。
举例:
题解
迭代解法
迭代方法通过寻找到待删除节点并记录其父节点,然后根据节点类型进行讨论处理来完成。
java代码
//删除二叉搜索树的节点 迭代解法
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
if(null==root)return null;
//找到待删除节点
TreeNode node=root;
TreeNode parent=null;//待删除节点的父节点
while(node!=null){
if(key==node.val)break;
parent=node;//若key存在,则parent一定正确
if(node.val<key)node=node.right;
else node=node.left;
}
//为空则表示没找到
if(null==node)return root;
//此时的node就是待删除节点
//如果有两个叶子节点,找后继节点,替换值,并指向待删除后驱节点
if(null!=node.left&&null!=node.right){
parent=node;
//找到后继节点
TreeNode replace =node.right;
while(replace.left!=null){
parent=replace;//更新父节点
replace=replace.left;
}
//此时replace就是后继节点,替换值
node.val=replace.val;
//指向待删除的后继节点
node=replace;
}
//1.只有一个子节点 2.叶子节点
TreeNode replace=node.left!=null?node.left:node.right;//获取到子节点
if(replace==null){//叶子节点
if(root==node)root=null;//为父节点
else if(node==parent.left)parent.left=null;//如果删除节点是父节点的左节点
else parent.right=null;
}else{//删除节点有一个子节点
if(root==node){//如果是根节点
root=replace;//更新根节点
}else{//用父节点直接连接子节点
if(node==parent.left)parent.left=replace;
else parent.right=replace;
}
}
return root;
}
}
c++代码
class Solution {
public:
TreeNode* deleteNode(TreeNode* root, int key) {
if(!root)return root;
//找到待删除节点
TreeNode* node=root;
TreeNode* parent=NULL;//待删除节点的父节点
while(node){
if(key==node->val)break;
parent=node;//若key存在,则parent一定正确
if(node->val<key){
node=node->right;
}else if(node->val>key){
node=node->left;
}
}
//为空则表示没找到
if(!node)return root;
//此时的node就是待删除节点
//如果有两个叶子节点,找后继节点,替换值,并指向待删除后驱节点
if(node->left&&node->right){
parent=node;
//找到后继节点
TreeNode* replace =node->right;
while(replace->left){
parent=replace;//更新父节点
replace=replace->left;
}
//此时replace就是后继节点,替换值
node->val=replace->val;
//指向待删除的后继节点
node=replace;
}
//1.只有一个子节点 2.叶子节点
TreeNode* replace=node->left!=NULL?node->left:node->right;//获取到子节点
if(!replace){//叶子节点
if(root==node){//为父节点
root=NULL;
return root;
}
if(node==parent->left){//如果删除节点是父节点的左节点
parent->left=NULL;
}else{
parent->right=NULL;
}
}else{//删除节点有一个子节点
if(root==node){//如果是根节点
root=replace;//更新根节点
}else{//用父节点直接连接子节点
if(node==parent->left)parent->left=replace;
else parent->right=replace;
}
}
return root;
}
};
递归解法
递归解法中先对函数deleteNode做出定义,删除根节点为root的树中的key节点,并返回新的根节点。如果当前root节点不是key节点且值比key小,则可以对当前root节点的右节点使用deleteNode函数,即删除根节点为root.right的树中的key节点,并返回该树的新头节点,由于右子树的根节点可能发生变化,所以需要对当前节点的右子节点进行更新。若是root的节点的值大于key,则是对左节点进行操作。
if(root.val>key){//在左边
root.left=deleteNode(root.left,key);
}else if(root.val<key){//在右边
root.right=deleteNode(root.right,key);
}
如果当前root节点是待删除的节点则:
- 叶子节点:直接删除,即返回null
- 有一个子节点的节点:返回它唯一的子节点供其头节连接
- 有两个子节点:找到后继节点,替换值,再使用deleteNode方法删除后继节点(后继节点一定没有两个子节点)
//为叶子节点或有一个子节点的节点
if(root.left==null)return root.right;
if(root.right==null)return root.left;
//有两个子节点的节点
TreeNode successor=findSuccessor(root.right);
root.val=successor.val;
root.right=deleteNode(root.right,root.val);
java代码
/**
* 递归解法
*/
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
if(null==root)return null;
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==null)return root.right;
if(root.right==null)return root.left;
//有两个子节点的节点
TreeNode successor=findSuccessor(root.right);
root.val=successor.val;
root.right=deleteNode(root.right,root.val);
}
return root;
}
//找到最右侧节点
private TreeNode findSuccessor(TreeNode node){
while (node.left != null)
node=node.left;
return node;
}
}
c++代码
class Solution {
public:
TreeNode* deleteNode(TreeNode* root, int key) {
if(!root) return root;
if(key<root->val)root->left=deleteNode(root->left,key);
if(key>root->val)root->right=deleteNode(root->right,key);
if(key==root->val){
if(!root->left&&!root->right)return NULL;
if(root->left&&!root->right)return root->left;
if(!root->left&&root->right)return root->right;
TreeNode* temp=root->right;
while(temp->left)temp=temp->left;
root->val=temp->val;
root->right=deleteNode(root->right,root->val);
}
return root;
}
};
标签:node,right,java,LeetCode450,c++,key,root,节点,left 来源: https://blog.csdn.net/Demon_LMMan/article/details/114300878