1. 题目
给出二叉树的根节点 root,树上每个节点都有一个不同的值。
如果节点值在 to_delete 中出现,我们就把该节点从树上删去,最后得到一个森林(一些不相交的树构成的集合)。
返回森林中的每棵树。你可以按任意顺序组织答案。
示例:
输入:root = [1,2,3,4,5,6,7], to_delete = [3,5]
输出:[[1,2,null,4],[6],[7]]
提示:
树中的节点数最大为 1000。
每个节点都有一个介于 1 到 1000 之间的值,且各不相同。
to_delete.length <= 1000
to_delete 包含一些从 1 到 1000、各不相同的值。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/delete-nodes-and-return-forest
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2. 解题
- 要删除的放入哈希表,方便快速查找
- 递归遍历,记录父节点,和左右方向
- 如果要删除,断开父节点,子节点,遍历子节点
- 不删除,且父节点为空,加入答案
class Solution {
unordered_set<int> s;
vector<TreeNode*> ans;
public:
vector<TreeNode*> delNodes(TreeNode* root, vector<int>& to_delete) {
if(!root)
return {};
for(int del : to_delete)
s.insert(del);//哈希快速查找
order(root, NULL, 0);
return ans;
}
void order(TreeNode* root, TreeNode* father, int dir)
{ //参数,当前节点,其父节点,是父节点的左节点还是右节点
if(!root)
return;
if(s.count(root->val))//root需要删除
{
if(father)//要删除的节点有父节点
{
if(dir==0)//是左边过来的
father->left = NULL;//断开与父节点的链接
else
father->right = NULL;
}
TreeNode *l = root->left, *r = root->right;//当前节点的左右子节点
root->left = NULL;//断开子的链接
root->right = NULL;//断开子的链接
order(l, NULL, 0);//遍历左子,其父节点断开了,为空,第三个参数随意
order(r, NULL, 0);//遍历右子
}
else//root不用删除
{
if(!father)//如果没有父节点了,新的树根,加入答案
ans.push_back(root);
order(root->left, root, 0);//遍历左子,第三个参数0表示左
order(root->right, root, 1);//遍历右子,第三个参数1表示右
}
}
};