当前位置:网站首页>【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
边栏推荐
- SM2246EN+闪迪15131
- 项目配置了eslint,编辑器没有关闭eslint功能的情况下,eslint没有生效
- 英语没学好到底能不能做coder,别再纠结了先学起来
- 二叉树终章
- matlab 将三角剖分结果保存为STL文件
- Unity 如何拖拉多个组件中的一个
- QQmlApplicationEngine failed to load component qrc:/main.qml:-1 No such file or directory
- KubeVela 1.4:让应用交付更安全、上手更简单、过程更透明
- Task01: getting to know database and SQL (Note 1)
- composer
猜你喜欢

标配10个安全气囊,奇瑞艾瑞泽8安全防护无死角

码蹄集 - MT3435 · 赋值 - 二分图问题 - 图文讲解

This morning, investors began to travel collectively

说实话ThreadLocal真不是啥高级的东西

2022年高考都结束了,还有人真觉得程序员下班后不需要学习吗?

History, selection strategy and in-depth evaluation of note taking software

MySQL billing Statistics (Part 1): MySQL installation and client dbeaver connection

无线充U型超声波电动牙刷方案开发

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

盘点华为云GaussDB(for Redis)六大秒级能力
随机推荐
await和async
VR全景拍摄为什么要加盟?巧借资源实现共赢
VR全景添加对比功能,让差异化效果展示更直观!
IT外包驻场人员怎么定位自己的痛点?
码蹄集 - MT3111· 赋值
【NLP】【TextCNN】 文本分类
2022 最新 JCR正式发布全球最新影响因子名单(前600名)
企业中通过组策略管理Edge浏览器设置(IE模式、主页绑定等)
条件编译
今早,投资人开始集体出差
手机炒股开户安全嘛!?
“更福特、更中国”拨云见日,长安福特王牌产品订单过万
英语没学好到底能不能做coder,别再纠结了先学起来
Redis入门到精通01
arthas调试 确定问题工具包
阿里天池SQL训练营学习笔记5
当我们在看待产业互联网的时候,总是会站在消费互联网的对立面来看待它
杭州炒股开户选择手机办理安全吗?
JVM FAQs
哪个券商佣金的佣金最低?另外,手机开户安全么?