当前位置:网站首页>【450. 删除二叉搜索树中的节点】
【450. 删除二叉搜索树中的节点】
2022-06-30 19:13:00 【Sugar_wolf】
来源:力扣(LeetCode)
描述:
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
首先找到需要删除的节点;
如果找到了,删除它。
示例 1:
输入:root = [5,3,6,2,4,null,7], key = 3
输出:[5,4,6,2,null,null,7]
解释:给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。
一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。
另一个正确答案是 [5,2,6,null,4,null,7]。

示例 2:
输入: root = [5,3,6,2,4,null,7], key = 0
输出: [5,3,6,2,4,null,7]
解释: 二叉树不包含值为 0 的节点
示例 3:
输入: root = [], key = 0
输出: []
提示:
- 节点数的范围 [0, 104].
- -105<= Node.val <= 105
- 节点值唯一
- root 是合法的二叉搜索树
- -105 <= key <= 105
方法一:递归
思路


代码:
class Solution {
public:
TreeNode* deleteNode(TreeNode* root, int key) {
if (root == nullptr) {
return nullptr;
}
if (root->val > key) {
root->left = deleteNode(root->left, key);
return root;
}
if (root->val < key) {
root->right = deleteNode(root->right, key);
return root;
}
if (root->val == key) {
if (!root->left && !root->right) {
return nullptr;
}
if (!root->right) {
return root->left;
}
if (!root->left) {
return root->right;
}
TreeNode *successor = root->right;
while (successor->left) {
successor = successor->left;
}
root->right = deleteNode(root->right, successor->val);
successor->right = root->right;
successor->left = root->left;
return successor;
}
return root;
}
};
执行用时:28 ms, 在所有 C++ 提交中击败了83.08%的用户
内存消耗:31.8 MB, 在所有 C++ 提交中击败了71.37%的用户
复杂度分析
时间复杂度: O(n),其中 n 为 root 的节点个数。最差情况下,寻找和删除 successor 各需要遍历一次树。
空间复杂度: O(n),其中 n 为 root 的节点个数。递归的深度最深为 O(n)。
方法二:迭代
思路
方法一的递归深度最多为 n,而大部分是由寻找值为 key 的节点贡献的,而寻找节点这一部分可以用迭代来优化。寻找并删除 successor 时,也可以用一个变量保存它的父节点,从而可以节省一步递归操作。
代码:
class Solution {
public:
TreeNode* deleteNode(TreeNode* root, int key) {
TreeNode *cur = root, *curParent = nullptr;
while (cur && cur->val != key) {
curParent = cur;
if (cur->val > key) {
cur = cur->left;
} else {
cur = cur->right;
}
}
if (!cur) {
return root;
}
if (!cur->left && !cur->right) {
cur = nullptr;
} else if (!cur->right) {
cur = cur->left;
} else if (!cur->left) {
cur = cur->right;
} else {
TreeNode *successor = cur->right, *successorParent = cur;
while (successor->left) {
successorParent = successor;
successor = successor->left;
}
if (successorParent->val == cur->val) {
successorParent->right = successor->right;
} else {
successorParent->left = successor->right;
}
successor->right = cur->right;
successor->left = cur->left;
cur = successor;
}
if (!curParent) {
return cur;
} else {
if (curParent->left && curParent->left->val == key) {
curParent->left = cur;
} else {
curParent->right = cur;
}
return root;
}
}
};
执行用时:28 ms, 在所有 C++ 提交中击败了83.08%的用户
内存消耗:31.8 MB, 在所有 C++ 提交中击败了86.56%的用户
复杂度分析
时间复杂度: O(n),其中 n 为 root 的节点个数。最差情况下,需要遍历一次树。
空间复杂度: O(1)。使用的空间为常数。
author:LeetCode-Solution
边栏推荐
猜你喜欢

正则系列之字符类

Cartoon | has Oracle been abandoned by the new era?

6-1漏洞利用-FTP漏洞利用

Growth summer challenge is coming, exclusive community welfare is coming ~ get CSDN customized T-shirt for free

Promise from recognition to use

Character class of regular series

今早,投资人开始集体出差

测试人进阶技能:单元测试报告应用指南

【NLP】【TextCNN】 文本分类

解决arm_release_ver of this libmali is ‘g2p0-01eac0‘,rk_so_ver is ‘4‘,libgl1-mesa-dev不会被安装,存在未满足的依赖关系
随机推荐
说实话ThreadLocal真不是啥高级的东西
为什么越来越多的人选择云渲染?
MQ优缺点(2022.5.2-5.8)
一文读懂目标检测:R-CNN、Fast R-CNN、Faster R-CNN、YOLO、SSD「建议收藏」
Promise from recognition to use
[solved] how does Tiktok cancel paying attention to the cancelled account
如何使用robots.txt及其详解
JVM FAQs
matlab 将三角剖分结果保存为STL文件
内存数据库如何发挥内存优势?
【NLP】【TextCNN】 文本分类
盘点华为云GaussDB(for Redis)六大秒级能力
ROS advertisement data publishing tips - latch configuration
Inventory the six second level capabilities of Huawei cloud gaussdb (for redis)
Safe holidays without holidays, VR traffic makes children travel safely | Guangzhou Sinovel viewpoint
《微信小程序-基础篇》带你了解小程序中的生命周期(二)
达梦数据库重新初始化实例操作记录
The project is configured with eslint. When the editor does not close the eslint function, the eslint does not take effect
MySQL数据库查询优化
arthas调试 确定问题工具包