Given a binary tree root
and an integer target
, delete all the leaf nodes with value target
.
Note that once you delete a leaf node with value target
, if its parent node becomes a leaf node and has the value target
, it should also be deleted (you need to continue doing that until you cannot).
Example 1:
Input: root = [1,2,3,2,null,2,4], target = 2 Output: [1,null,3,null,4] Explanation: Leaf nodes in green with value (target = 2) are removed (Picture in left). After removing, new nodes become leaf nodes with value (target = 2) (Picture in center).
Example 2:
Input: root = [1,3,3,3,2], target = 3 Output: [1,3,null,null,2]
Example 3:
Input: root = [1,2,null,2,null,2], target = 2 Output: [1] Explanation: Leaf nodes in green with value (target = 2) are removed at each step.
Constraints:
[1, 3000]
.1 <= Node.val, target <= 1000
This problem involves traversing a binary tree and removing leaf nodes that match a given target value. The key is to recursively remove leaves and then check if the parent node also becomes a leaf node with the target value, continuing the process until no more leaf nodes with the target value exist.
Approach:
We employ a Depth-First Search (DFS) post-order traversal to efficiently solve this problem. Post-order traversal ensures that we process child nodes before their parent. This is crucial because we need to know if a node has become a leaf node after its children have been processed.
Algorithm:
Base Case: If the current node is null
, we return null
.
Recursive Calls: Recursively call the function on the left and right subtrees. This processes the children first.
Leaf Node Check: After processing the children, check if the current node is a leaf node (both left
and right
children are null
) and its value is equal to the target
. If it is, return null
to effectively remove the leaf node from the tree.
Return Node: If the node is not a leaf node with the target value, return the current node. This propagates the updated subtree structure back up the recursion.
Time Complexity Analysis:
The algorithm visits each node in the tree exactly once during the recursive traversal. Therefore, the time complexity is O(N), where N is the number of nodes in the binary tree.
Space Complexity Analysis:
The space complexity is determined by the maximum depth of the recursion stack. In the worst case, this is equal to the height of the binary tree. For a skewed tree, the height can be N, while for a balanced tree, it is log₂(N). Therefore, the space complexity is O(H), where H is the height of the binary tree. In the worst case, this becomes O(N).
Code Explanation (Python Example):
class Solution:
def removeLeafNodes(self, root: Optional[TreeNode], target: int) -> Optional[TreeNode]:
if root is None: # Base case: empty subtree
return None
root.left = self.removeLeafNodes(root.left, target) #Recursive call on left subtree
root.right = self.removeLeafNodes(root.right, target) # Recursive call on right subtree
if root.left is None and root.right is None and root.val == target: #Check if leaf and target value
return None #Remove the leaf node
return root #Otherwise, return the current node
The other language examples follow the same algorithmic structure, differing only in syntax and specific data structure implementations. The time and space complexity remain consistent across all implementations.