Leetcode:450. 刪除二叉搜尋樹中的節點
阿新 • • 發佈:2018-12-11
給定一個二叉搜尋樹的根節點 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
解題思路:
遞迴。
- 利用遞迴查詢數值為key的節點,如果沒有,原封不動地返回原來地樹。
- 找到待刪除地點node,node地狀態可能有下面幾種。
- node沒有孩子,那麼直接刪除這個節點,返回root,如果root,恰好被刪除,那麼返回null。
- node只有左孩子,將node->left替換node。
- node有兩個孩子。找到右子樹中最靠左(數值最小)的點去替代node,如果node->right恰好是最左的點,那麼,將node的左子樹直接嫁接到node->right->left。再將node->right替換node。
- 最終返回root,注意root可能是待刪除的點。
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; }; |