LeetCode Notes_#450_刪除二叉搜尋樹中的節點
阿新 • • 發佈:2020-08-14
LeetCode Notes_#450_刪除二叉搜尋樹中的節點
Contents
題目
給定一個二叉搜尋樹的根節點 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
思路分析
BST的刪除操作是BST資料結構最難的一個操作,更詳細的講解可以參考 《演算法第四版》3.2.3.5小節。
主要分為兩步:
1. 找到待刪除節點
不能把搜尋和刪除兩步操作分離,因為刪除節點後,還要把新的子樹連線到父節點。這個操作只能通過遞迴的回溯來進行。
if(key < root.val){
//因為key節點在左子樹當中,所以就縮小範圍,在左子樹當中刪除key節點
root.left = deleteNode(root.left, key);
//遞迴呼叫結束,把刪除後的子樹連線到root上面
return root;
}
else if(key > root.val){
//同理,右子樹的情況
root.right = deleteNode(root.right, key);
return root;
}
2. 刪除待刪除節點
刪除操作需要分情況考慮,有如下的三種情況:
1. 待刪除節點沒有子節點,可以直接將其刪除
2. 待刪除節點只有一個子節點,用它的子節點代替它
3. 待刪除節點有兩個子節點,則需要用待刪除節點在中序遍歷中的前驅或者後繼代替它
- 前驅節點一定是左子樹的最大節點(也就是左子樹最右下角的節點)
- 後繼節點一定是右子樹的最小節點(也就是右子樹最左下角的節點)
總結來說,BST在刪除節點之前,中序遍歷有序。刪除節點之後,中序遍歷應該還是有序的。
解答
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
if(root == null) return null;
if(key < root.val){
//因為key節點在左子樹當中,所以就縮小範圍,在左子樹當中刪除key節點
root.left = deleteNode(root.left, key);
//遞迴呼叫結束,把刪除後的子樹連線到root上面
return root;
}
else if(key > root.val){
//同理,右子樹的情況
root.right = deleteNode(root.right, key);
return root;
}
//key == root.val,即遇到的root剛好就是待刪除的節點
else{
//左子樹為null,用右子樹替代key節點(左右子樹同時為null,也正確)
if(root.left == null) return root.right;
////右子樹為null,用左子樹替代key節點
else if(root.right == null) return root.left;
else{
//後繼節點其實就是右子樹裡的最小值
TreeNode successor = min(root.right);
//在右子樹當中需要刪除successor,因為successor要和key交換位置
successor.right = deleteMin(root.right);
//左子樹沒有變化
successor.left = root.left;
return successor;
}
}
}
//找到BST當中的最小節點,返回這個節點
private TreeNode min(TreeNode node){
if(node.left == null) return node;
return min(node.left);
}
//刪除BST當中的最小節點,返回刪除之後的樹的根節點
private TreeNode deleteMin(TreeNode node){
//找到最小節點,沒有左孩子,用它的右子樹代替它
if(node.left == null) return node.right;
node.left = deleteMin(node.left);
return node;
}
}
複雜度分析
時間複雜度:O(h)
空間複雜度:O(1)