1. 程式人生 > >Leetcode:450. 刪除二叉搜尋樹中的節點

Leetcode:450. 刪除二叉搜尋樹中的節點

給定一個二叉搜尋樹的根節點 root 和一個值 key,刪除二叉搜尋樹中的 key 對應的節點,並保證二叉搜尋樹的性質不變。返回二叉搜尋樹(有可能被更新)的根節點的引用。

一般來說,刪除節點可分為兩個步驟:

  1. 首先找到需要刪除的節點;
  2. 如果找到了,刪除它。

說明: 要求演算法時間複雜度為 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. 利用遞迴查詢數值為key的節點,如果沒有,原封不動地返回原來地樹。
  2. 找到待刪除地點node,node地狀態可能有下面幾種。
  3. node沒有孩子,那麼直接刪除這個節點,返回root,如果root,恰好被刪除,那麼返回null。
  4. node只有左孩子,將node->left替換node。
  5. node有兩個孩子。找到右子樹中最靠左(數值最小)的點去替代node,如果node->right恰好是最左的點,那麼,將node的左子樹直接嫁接到node->right->left。再將node->right替換node。
  6. 最終返回root,注意root可能是待刪除的點。

C++程式碼
class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        TreeNode* node = find(root, key);
        if (node == NULL) return root;
        if (!node->right) {
            if (!key_father) return node->left;
            if (key_father->left == node) key_father->left = node->left;
            else key_father->right = node->left;
            return root;
        }
        if (!node->right->left) {
            node->right->left = node->left;
            if (!key_father) return node->right;
            if (key_father->left == node) key_father->left = node->right;
            else key_father->right = node->right;
            return root;
        }
        //查詢node右子樹中最左的點。
        TreeNode *left, *left_father;
        left_father = node->right;
        left = left_father->left;
        while (left) {
            if (left->left) {
                left_father = left;
                left = left->left;
            }
            else break;
        }
        left_father->left = left->right;
        left->left = node->left;
        left->right = node->right;
        if (!key_father) {
            return left;
        }
        if (key_father->left == node) {
            key_father->left = left;
        }
        else {
            key_father->right = left;
        }
        node->left = NULL;
        node->right = NULL;
        delete node;
        return root;
    }
    TreeNode* find(TreeNode* root, int key) {
        if (!root) return NULL;
         if (root->val == key) return root;
        if ((root->left)&&root->left->val == key || (root->right)&&root->right->val == key) key_father = root;
        if (root->val > key) return find(root->left, key);
        if (root->val < key) return find(root->right, key);
    }
    TreeNode* key_father;
};