[Leetcode解題] 1110. Delete Nodes And Return Forest - DFS解
4 October 2024
medium
dfs
題目
1110. Delete Nodes And Return Forest
當你有一棵二元樹,其中每個節點的值都不一樣,我們的目標是刪除一些節點,這些節點的值在一個叫 to_delete
的列表裡。當這些節點被刪除後,樹會被分成幾個不連接的小樹,這些小樹被稱為森林。你需要返回這些小樹的根節點,順序沒有關係。
解題思路
這題的重點在於,我們需要用遞迴的方式遍歷整棵樹,逐一檢查每個節點是不是要被刪掉。如果某個節點需要被刪除,我們就把它的子節點(如果有的話)加入到森林裡,然後把這個節點刪掉。最終,留下來的節點會形成幾棵新的小樹,這些小樹就是我們的「森林」。
具體步驟:
- 使用深度優先搜索 (DFS) 遍歷整棵樹,並檢查每個節點。
- 如果節點的值存在於
to_delete
列表中,將它的左子節點和右子節點(如果存在)加入到森林中,然後刪除此節點。 - 遞迴結束後,檢查根節點,如果根節點本身未被刪除,將其加入森林。
- 使用一個hash set
toDelete
來快速查找要刪除的節點。
Python 實作
# 定義二元樹節點
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def delNodes(self, root: TreeNode, to_delete: list[int]) -> list[TreeNode]:
toDelete = set(to_delete) # 使用集合來提高查找效率
forest = [] # 存放結果的森林
def dfs(node: TreeNode) -> TreeNode:
if not node:
return None
# 遞迴處理左子樹和右子樹
node.left = dfs(node.left)
node.right = dfs(node.right)
# 如果當前節點需要被刪除
if node.val in toDelete:
if node.left:
forest.append(node.left) # 左子樹加入森林
if node.right:
forest.append(node.right) # 右子樹加入森林
return None # 刪除當前節點,返回 None
return node # 保留當前節點
# 處理根節點
if dfs(root):
forest.append(root)
return forest
C++ 實作
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<TreeNode*> forest;
void dfs(TreeNode* &root, const unordered_set<int> &toDelete){
if (!root) return;
dfs(root -> left, toDelete);
dfs(root -> right, toDelete);
if (toDelete.find(root->val)!=toDelete.end()){
if (root -> left) forest.push_back(root->left);
if (root -> right) forest.push_back(root->right);
delete root;
root = nullptr;
}
return;
}
vector<TreeNode*> delNodes(TreeNode* root, vector<int>& to_delete) {
unordered_set<int> toDelete(to_delete.begin(), to_delete.end());
dfs(root, toDelete);
if (root) forest.push_back(root);
return forest;
}
};
時間複雜度分析
- 時間複雜度:
O(N)
,其中N
是樹中節點的數量。每個節點只被訪問一次,並且每次訪問的操作都是常數時間。 - 空間複雜度:
O(N)
,最壞情況下,遞迴堆疊需要存儲樹的所有節點。