1. 程式人生 > >[LeetCode] 450. Delete Node in a BST

[LeetCode] 450. Delete Node in a BST

Delete Node in a BST

Given a root node reference of a BST and a key, delete the node with the given key in the BST. Return the root node reference (possibly updated) of the BST.
Basically, the deletion can be divided into two stages:
1. Search for a node to remove.
2. If the node is found, delete the node.
Note:

Time complexity should be O(height of tree).
Example:
在這裡插入圖片描述

解析

刪除給定值得節點

解法1:遞迴

首先判斷根節點是否為空,由於BST的性質,可以遞迴定位到要刪除的節點。當前節點不等於key時,根據大小關係遞迴呼叫左右節點。
當前節點就是要刪除的節點時,首先判斷是否有一個子節點不存在,將root指向存在的子節點;當左右子節點都存在時,在右子樹中找到最小值得節點,並將其值賦給當前節點,再遞迴呼叫右子樹刪除其最小節點。

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if(!root) return NULL;
        if(root->val > key)
            root->left = deleteNode(root->left, key);
        else if(root->val < key)
            root->right = deleteNode(root->right, key);
        else{
            if(!root->left || !root->right)
                root = root->left ? root->left:root->right;
            else{
                TreeNode* cur = root->right;
                while(cur->left) cur = cur->left;
                root->val = cur->val;
                root->right = deleteNode(root->right, cur->val);
            }
        }
        return root;
    }
};

解法2:迭代

首先構建一個父節點pre以及當前節點cur,找到key的節點位置為cur,如果cur為空返回root,如果pre為空說明刪除節點是根節點,呼叫del函式刪除cur,如果刪除節點是pre->left,呼叫del刪除cur,並且pre->left=del(cur),反之,pre->right=del(cur)。
下面解釋刪除函式del(node)。
刪除函式是為了刪除當前節點,所以當node為葉子結點時,返回NULL;
當node有一個子節點時,返回那個子節點;
當node有兩個子節點時,先在右子樹中找到最小值節點cur, 並記錄其父節點pre,並賦值給node,當pre為node時,node->right = cur->right,反之,pre->right = cur->right;返回node。

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        TreeNode* cur = root, *pre = NULL;
        while(cur){
            if(cur->val == key) break;
            pre = cur;
            if(cur->val > key)
                cur = cur->left;
            else
                cur = cur->right;
        }
        if(!cur) return root;
        if(!pre) return del(cur);
        if(pre->left && pre->left->val == key) 
            pre->left = del(cur);
        else
            pre->right = del(cur);
        return root;
    }
    
    TreeNode* del(TreeNode* node){
        if(!node->left && !node->right) return NULL;
        if(!node->left || !node->right)  
            return node->left ? node->left : node->right;
        TreeNode* pre = node, *cur = node->right;
        while(cur->left){
            pre = cur;
            cur = cur->left;
        }
        node->val = cur->val;
        if(pre == node)
            node->right = cur->right;
        else
            pre->left = cur->right;
        return node;
    }
};

解法3:通用二叉樹

遍歷所有節點,然後刪除值為key的節點

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if (!root) return NULL;
        if (root->val == key) {
            if (!root->right) return root->left;
            else {
                TreeNode *cur = root->right;
                while (cur->left) cur = cur->left;
                swap(root->val, cur->val);
            }
        }
        root->left = deleteNode(root->left, key);
        root->right = deleteNode(root->right, key);
        return root;
    }
};

參考

http://www.cnblogs.com/grandyang/p/6228252.html