欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

LeetCode 450. 删除二叉搜索树中的节点(C++)

程序员文章站 2022-05-20 07:58:47
...

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

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

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

示例:

root = [5,3,6,2,4,null,7]
key = 3

    5
   / \
  3   6
 / \   \
2   4   7

给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。

一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。

    5
   / \
  4   6
 /     \
2       7

另一个正确答案是 [5,2,6,null,4,null,7]。

    5
   / \
  2   6
   \   \
    4   7

思路:

找到需要删除的节点之后,关于节点删除的规则如下:
1. 如果该节点是叶子节点,直接删除该节点即可。
2. 如果该节点不是叶子节点,但是只有左孩子或者右孩子的话,先交换该节点与其左孩子或者右孩子的值,然后删除其左孩子或者右孩子。
3. 如果该节点既有左孩子,又有右孩子的话,可以采用如下方式进行调整(这里对该节点的右子树进行调整,左子树调整同理)
(1)先新建一个指针,指向要删除节点的右孩子。
(2)由于右孩子可能本身存在左孩子,即delNode->right->left != NULL,而delNode->right->left->val是小于delNode->right->val的,所以直接向delNode->right->val赋值给要删除的节点是不可取的,因此要先要找到删除节点的右子树中的最小节点,即递归判断删除节点的右孩子的左孩子是否存在。
(3)找到删除节点右子树的最小节点minRNode,将其与要删除的节点delNode交换取值,然后删除minRNode

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if(root == NULL)
            return NULL;
        if(root->val == key){
            if(root->left != NULL && root->right != NULL){
                TreeNode* minRNode = root->right;
                while(minRNode->left != NULL)
                    minRNode = minRNode->left;
                root->val = minRNode->val;
                root->right = deleteNode(root->right, minRNode->val);
            }
            else{
                if(root->left != NULL){ //仅有左孩子
                    root->val = root->left->val;
                    delete(root->left);
                }
                else if(root->right != NULL){   //仅有右孩子
                    root->val = root->right->val;
                    delete(root->right);
                }
                else{   //无孩子
                    delete(root);
                }

            }
            return root;
        }
        if(key > root->val)
            root->right = deleteNode(root->right, key);
        else if(key < root->val)
            root->left = deleteNode(root->left, key);
        return root;
    }
};