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

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.二是停在非根节点 的时候,找前一个节点的指针 进行操作

相关推荐
田梓燊1 天前
力扣:23.合并 K 个升序链表
算法·leetcode·链表
re林檎1 天前
算法札记——4.27
算法
数据牧羊人的成长笔记1 天前
逻辑回归与Softmax回归
算法·回归·逻辑回归
郑州光合科技余经理1 天前
同城O2O海外版二次开发实战:从支付网关到配送算法
开发语言·前端·后端·算法·架构·uni-app·php
d111111111d1 天前
STM32-UART封装问题解析
笔记·stm32·单片机·嵌入式硬件·学习·算法
Jiangxl~1 天前
IP数据云如何为不同行业提供精准IP查询与风险防控解决方案?
网络·网络协议·tcp/ip·算法·ai·ip·安全架构
李伟_Li慢慢1 天前
wolfram详解山峦算法
前端·算法
counting money1 天前
prim算法最小生成树(java)
算法
澈2071 天前
C++面向对象:类与对象核心解析
c++·算法
用户690673881921 天前
基于无人机的单目测距系统,平均误差仅2.12%
算法