代码随想录二刷 | 二叉树| 删除二叉搜索树中的节点

代码随想录二刷 | 二叉树| 删除二叉搜索树中的节点

题目描述

450.删除二叉搜索树中的节点

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。

一般来说,删除节点可分为两个步骤:

首先找到需要删除的节点; 如果找到了,删除它。 说明: 要求算法时间复杂度为 O ( h ) O(h) O(h),h 为树的高度。

示例:
在这里插入图片描述

解题思路

递归三部曲

  1. 确定递归函数参数以及返回值
    参数:根节点与值key
    返回值:TreeNode*
    TreeNode* deleteNode(TreeNode* root, int key)
    
  2. 确定递归函数的终止条件
    遇到空就返回。
    if (root == nullptr) return root;
    
  3. 确定单层递归的逻辑
    情况一:没找到删除的节点,遍历到空节点直接返回
    情况二:找到删除的节点,左右孩子都为空,删除节点,返回NULL为根节点。
    情况三:找到删除的节点,删除节点的左孩子为空,右孩子不为空,删除节点,右孩子补位,返回右孩子为根节点。
    情况四:找到删除的节点,删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点。
    情况五:找到删除的节点,左右孩子节点都不为空,则将删除节点的左子树头节点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,返回删除节点右孩子为新的根节点。
    if (root->val == key) {
    	// 情况二、情况三
    	if (root->left == nullptr) return root->right;
    	// 情况四
    	else if (root->right == nullptr) return root->left;
    	// 情况五
    	else {
    		TreeNode* cur = root->right; // 找右子树最左面的节点
    		while (cur->left != nullptr) {
    			cur = cur->left;
    		}
    		cur->left = root->left; // 把要删除的节点的左子树放在cur的左孩子位置
    		TreeNode* temp = root;// 保存一下root
    		root = root->right; // 返回旧root的右孩子作为新root
    		delete temp; // 释放内存
    		return root;
    	}
    }
    
    这里相当于把新的节点返回给上一层,上一层就要用 root->left 或者 root->right接住,代码如下:
    if (root->val > key) root->left = deleteNode(root->left, key);
    if (root->val < key) root->right = deleteNode(root->right, key);
    return root;
    

代码实现

class Solution {
public:
	TreeNode* deleteNode(TreeNode* root, int key) {
		if (root == nullptr) return root; // 情况一
		if (root->val == key) {
			// 情况二
			if (root->left == nullptr && root->right == nullptr) {
				delete root;
				return nullptr;
			} else if (root->left == nullptr) { // 情况三
				auto retNode = root->right;
				delete root;
				return retNode;
			} else if (root->right == nullptr) { // 情况四
				auto retNode = root->left;
				delete root;
				return retNode;
			} else { // 情况五
				TreeNode* cur = root->right; // 找右子树最左面的节点
				while (cur->left != nullptr) {
					cur = cur->left;
				}
				cur->left = root->left; // 把要删除的节点的左子树放在cur的左孩子的位置
				TreeNode* temp = root; // 把root节点保存一下
				root = root->right; // 返回旧root的右孩子作为新root
				delete temp; // 释放内存
				return root;
			}
		}
		if (root->val > key) root->left = deleteNode(root->left, key);
		if (root->val < key) root->right = deleteNode(root->right, key);
	}
};
  • 21
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值