代码随想录刷题——二叉树篇(二十)

450. 删除二叉搜索树中的节点
递归法(二叉搜索树):

cpp 复制代码
class Solution{
public:
	TreeNode* deleteNode(TreeNode* root, int key){
		if(!root) return root;
		if(key==root->val){
			if(!root->left&&!root->right){
				delete root;
				return NULL;
			}
			else if(!root->left){
				TreeNode* rn=root->right;
				delete root;
				return rn;
			}
			else if(!root->right){
				TreeNode* ln=root->left;
				delete root;
				return ln;
			}
			else{
				TreeNode* tn=root->right;
				while(tn->left){
					tn=tn->left;
				}
				tn->left=root->left;
				TreeNode* tmp=root;
				root=root->right;
				delete tmp;
				return root;
			}
		}
		if(key<root->val) root->left=deleteNode(root->left,key);
		if(key>root->val) root->right=deleteNode(root->right,key);
		return root;
	}
};

递归法(普通二叉树):

cpp 复制代码
class Solution{
public:
	TreeNode* deleteNode(TreeNode* root,int key){
		if(!root) return NULL;
		if(root->val==key){
			if(!root->right) return root->left;
			TreeNode* tn=root->right;
			while(tn->left){
				tn=tn->left;
			}
			swap(root->val,tn->val);
		}
		root->left=deleteNode(root->left,key);
		root->right=deleteNode(root->right,key);
		return root;
	}
};

迭代法:

cpp 复制代码
class Solution{
private:
	TreeNode* deleteOneNode(TreeNode* root){
		if(!root) return root;
		else if(!root->left) return root->right;
		else if(!root->right) return root->left;
		else{
			TreeNode* tn=root->right;
			while(tn->left){
				tn=tn->left;
			}
			tn->left=root->left;
			return root->right;
		}
	}
public:
	TreeNode* deleteNode(TreeNode* root,int key){
		if(!root) return root;
		TreeNode* cur=root;
		TreeNode* pre=NULL;
		while(cur){
			if(key==cur->val) break;
			pre=cur;
			if(key<cur->val) cur=cur->left;
			else if(key>cur->val) cur=cur->right;
		}
		if(!pre) return root;
		else if(pre->left==cur) pre->left=deleteOneNode(cur);
		else if(pre->right==cur) pre->right=deleteOneNode(cur);
		return root;
	} 
};

其他:

(1)递归新理解:有返回值的递归存在一个上层类别节点选择递归路径下层类别节点向上递出返回值上层类别节点接受返回值 的过程。所以考虑的时候可以用从下向上从上向下的两种方式进行。

(2)判断时分支容易写错的问题:

cpp 复制代码
if(!root->left&&!root->right){
    delete root;
	return NULL;
}
else if(root->left){
	TreeNode* ln=root->left;
	delete root;
	return ln;
}
else if(root->right){
	TreeNode* rn=root->right;
	delete root;
	return rn;
}
else{
	TreeNode* tn=root->right;
	while(tn->left){
		tn=tn->left;
	}
	tn->left=root->left;
	TreeNode* tmp=root;
	root=root->right;
	delete tmp;
	return root;
}

对于本题来说,上面的分支是错误的,因为分支1是左右双空,原本想要的分支4是左右都非空,但此时分支2和分支3两个分支与分支4有重合。下面的分支则是正确的:

cpp 复制代码
if(!root->left&&!root->right){
	delete root;
	return NULL;
}
else if(!root->left){
	TreeNode* rn=root->right;
	delete root;
	return rn;
}
else if(!root->right){
	TreeNode* ln=root->left;
	delete root;
	return ln;
}
else{
	TreeNode* tn=root->right;
	while(tn->left){
		tn=tn->left;
	}
	tn->left=root->left;
	TreeNode* tmp=root;
	root=root->right;
	delete tmp;
	return root;
}

这里对自己来说有些容易写错,记录一下,一定要保证if else分支之间的情况是完全隔离的

(3)对于递归法 来说,访问操作 通常发生在当前层 ,而对于迭代法 来说,访问 通常发生在上一层

对于递归法 来说,访问和操作 通常发生在一起 ,而对于迭代法 来说,访问和操作 可以分成两步操作 可以单独写一个函数

(4)二叉搜索树的迭代法遍历访问特定值的节点

cpp 复制代码
while(cur){
	if(key==cur->val) break;
	pre=cur;
	if(key<cur->val) cur=cur->left;
	else cur=cur->right;
}

(5)pre二叉搜索树迭代法寻找中有两个作用:

a.一是判断是否停在根节点

b.二是停在非根节点 的时候,找前一个节点的指针 进行操作

相关推荐
tankeven1 天前
HJ162 ACM中的AC题
c++·算法
无尽的罚坐人生1 天前
hot 100 56. 合并区间
算法
kishu_iOS&AI1 天前
机器学习——归一化/标准化(特征工程预处理)
人工智能·算法·机器学习
美式请加冰1 天前
递归在二叉树搜索中的使用
算法
nianniannnn1 天前
力扣 76. 最小覆盖子串
c++·算法·leetcode
灰色小旋风1 天前
力扣K个一组翻转链表C++
c++·算法·leetcode
北冥有羽Victoria1 天前
TGC:深度时序图聚类的动态建模与时空平衡|ICLR 2024 深度解读
人工智能·python·算法·机器学习·支持向量机·聚类
manyikaimen1 天前
博派智能-运动控制技术-RTCP-五轴联动
c++·图像处理·qt·算法·计算机视觉·机器人·c#
Swift社区1 天前
LeetCode 401 二进制手表 - Swift 题解
算法·leetcode·swift
Darkwanderor1 天前
搜索优化——启发式搜索和A*算法
c++·算法·启发式搜索·a星搜索