Python O(n) DFS Recursion with Explanation
Time: O(n)\nSpace: O(n)\nAlgorithm: make the to_delete a hashset for O(1) look-up, check if the root needs to be included in the result or not, and proceed with
Time: O(n)\nSpace: O(n)\nAlgorithm: make the to_delete a hashset for O(1) look-up, check if the root needs to be included in the result or not, and proceed with DFS. For DFS we need to check if the specified node needs to be deleted, if yes, we need to update the parent node pointers and add in it\'s children to the result if they are not in the delete list. Then continue DFS keeping track of parent and where you came from (R or L).\n```\ndef delNodes(self, root, to_delete):\n        """\n        :type root: TreeNode\n        :type to_delete: List[int]\n        :rtype: List[TreeNode]\n        """\n        to_delete = set(to_delete)\n        if not root:\n            return []\n        self.res = [] if root.val in to_delete else [root]\n        self.dfs(root, None, "R", to_delete)\n        return self.res\n        \n    def dfs(self, node, parent, side, to_delete):\n        if node:\n            if node.val in to_delete:\n                if side == "R" and parent:\n                    parent.right = None\n                if side == "L" and parent:\n                    parent.left = None\n                if node.left and node.left.val not in to_delete:\n                    self.res.append(node.left)\n                if node.right and node.right.val not in to_delete:\n                    self.res.append(node.right)\n            self.dfs(node.left, node, "L", to_delete)\n            self.dfs(node.right, node, "R", to_delete)
['Depth-First Search', 'Recursion', 'Python']