Find Duplicate Subtrees - Complete Solution Guide
Find Duplicate Subtrees is LeetCode problem 652, a Medium level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
Given the root of a binary tree, return all duplicate subtrees . For each kind of duplicate subtrees, you only need to return the root node of any one of them. Two trees are duplicate if they have the same structure with the same node values . Example 1: Input: root = [1,2,3,4,null,2,4,null,null,4] Output: [[2,4],[4]] Example 2: Input: root = [2,1,1] Output: [[1]] Example 3: Input: root = [2,2,2,3,null,3,null] Output: [[2,3],[3]] Constraints: The number of the nodes in the tree will be in the ra
Detailed Explanation
The problem asks us to find all duplicate subtrees within a given binary tree. A duplicate subtree is defined as a subtree that has the same structure and node values as another subtree within the original tree. The task is to return a list containing the root nodes of all such duplicate subtrees. For each distinct type of duplicate subtree, we only need to return the root node of any *one* instance of it. This means if the same subtree appears multiple times, we only add the root node once to our result.
Solution Approach
The solution uses a Depth-First Search (DFS) traversal to visit each node in the binary tree. For each node, it constructs a unique string representation (serialization) of the subtree rooted at that node. This string representation encodes the structure and node values of the subtree. A hash table (`memo`) is used to store these string representations and assign unique IDs to each. A second hash table (`counts`) tracks how many times each unique ID has been encountered. If a subtree's ID appears twice in the `counts` table, it means we've found a duplicate, and we add the root of that subtree to our result list. The DFS function returns a unique ID for each subtree, allowing the parent node to construct its own subtree representation.
Step-by-Step Algorithm
- Step 1: Initialize data structures: `memo` (hash table to store subtree strings and IDs), `counts` (hash table to count the occurrences of each ID), `res` (list to store the root nodes of duplicate subtrees), and `current_id` (unique ID counter).
- Step 2: Define a recursive DFS function that takes a node as input.
- Step 3: Base case: If the node is `None` (empty), return a special ID (e.g., 0) indicating an empty subtree.
- Step 4: Recursively call DFS on the left and right children of the current node to get their respective IDs.
- Step 5: Construct a string representation (subtree_key) of the current subtree using the node's value and the IDs of its left and right subtrees. The representation should uniquely identify the subtree's structure and values (e.g., `node.val + ',' + left_id + ',' + right_id`).
- Step 6: Check if the subtree_key is already present in `memo`. If not, assign a new unique `current_id` to it and store it in `memo`.
- Step 7: Increment the count of the subtree's ID in the `counts` table.
- Step 8: If the count of the subtree's ID in `counts` is equal to 2, it means we've found a duplicate of this subtree, so append the current node to the `res` list. Note: We only add the node the first time we see the *second* instance.
- Step 9: Return the ID of the current subtree from the DFS function. This ID will be used by the parent node to construct its own subtree representation.
- Step 10: Call the DFS function on the root of the tree.
- Step 11: Return the `res` list containing the root nodes of the duplicate subtrees.
Key Insights
- Insight 1: We need a way to uniquely identify each subtree's structure and values. This is crucial for comparing subtrees to detect duplicates.
- Insight 2: Serializing the subtree into a string allows us to use a hash table (dictionary) to efficiently track the occurrence of each unique subtree structure.
- Insight 3: Using a unique ID for each subtree streamlines the counting process, avoiding string comparisons for every duplicate check.
Complexity Analysis
Time Complexity: O(n)
Space Complexity: O(n)
Topics
This problem involves: Hash Table, Tree, Depth-First Search, Binary Tree.
Companies
Asked at: PhonePe, Yandex.