1. 程式人生 > >LeetCode 450. 刪除二叉搜尋樹中的節點(C++)

LeetCode 450. 刪除二叉搜尋樹中的節點(C++)

給定一個二叉搜尋樹的根節點 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; } };