/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * TreeNode(int x) : val(x), left(nullptr, right(nullptr) {} * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} * }; */ class Solution { public: TreeNode* deleteNode(TreeNode* root, int key) { // 如果当前节点为空,直接返回空 if(root == nullptr) return root; // 找到要删除的节点 if(root->val == key) { // 情况1:节点是叶子节点(没有子节点) if(root->left == nullptr && root->right == nullptr) { delete root; return nullptr; } // 情况2:节点只有一个子节点(只有左子节点) else if(root->left != nullptr && root->right == nullptr) { auto node = root->left; delete root; return node; } // 情况3:节点只有一个子节点(只有右子节点) else if(root->left == nullptr && root->right != nullptr) { auto node = root->right; delete root; return node; } // 情况4:节点有两个子节点 else { // 找到右子树中的最小节点 TreeNode* cur = root->right; while(cur->left != nullptr) { cur = cur->left; } // 将当前节点的左子树接到右子树的最小节点的左子树上 cur->left = root->left; // 保留右子树 auto node = root; root = root->right; // 删除当前节点 delete node; return root; } } // 递归处理左子树 if(root->val > key) root->left = deleteNode(root->left, key); // 递归处理右子树 if(root->val < key) root->right = deleteNode(root->right, key); return root; } };
代码使用了递归的方法。主要思路是首先判断当前节点是否为空,如果为空,返回空。然后,根据当前节点的值与要删除的值的关系,递归地在左子树或右子树中删除这个节点。删除节点时,有几种情况需要考虑:
- 如果要删除的节点是叶子节点(即左右子节点都为空),直接删除该节点。
- 如果要删除的节点只有一个子节点,则用该子节点替换要删除的节点。
- 如果要删除的节点有两个子节点,则需要找到其后继节点(即右子树中的最小节点),然后用后继节点替换要删除的节点,并递归地删除后继节点。
这里简要解释一下代码的工作流程:
- 首先判断当前节点是否为空,如果为空,返回空。
- 如果当前节点的值等于要删除的值,根据是否有子节点进行不同的处理。
- 如果当前节点的值大于要删除的值,递归地在左子树中删除。
- 如果当前节点的值小于要删除的值,递归地在右子树中删除。
- 返回当前节点。
这个算法的时间复杂度是 O(h),其中 h 是树的高度。在最坏的情况下,可能需要遍历整个树来找到要删除的节点。空间复杂度也是 O(h),因为需要存储递归调用的栈。