Leetcode 2196: Create Binary Tree From Descriptions

You are given a list of triplets representing the structure of a binary tree. Each triplet
[parent, child, isLeft] indicates that parent is the parent of child, and if isLeft is 1, child is the left child of parent, otherwise, it’s the right child. Your task is to reconstruct the binary tree and return the root node.Problem
Approach
Steps
Complexity
Input: The input consists of a list of triplets where each triplet represents a parent-child relationship in a binary tree. The structure of the input is: `[parent, child, isLeft]`. The list contains information about all nodes of the tree.
Example: descriptions = [[10, 5, 1], [10, 20, 0], [5, 3, 1], [3, 2, 0]]
Constraints:
• 1 <= descriptions.length <= 10^4
• descriptions[i].length == 3
• 1 <= parent, child <= 10^5
• 0 <= isLeft <= 1
• The binary tree described by descriptions is valid.
Output: The output should be the root node of the reconstructed binary tree, represented as a binary tree node. The output should be in the form of an array representation of the tree starting from the root.
Example: [10, 5, 20, 3, 2]
Constraints:
• The output should represent the tree starting from the root node.
Goal: The goal is to reconstruct the binary tree from the descriptions and return its root node.
Steps:
• 1. Parse the descriptions to identify the root node (the node that does not have any parent).
• 2. Create a map to store the nodes as we build the tree.
• 3. For each triplet, connect the parent and child nodes as left or right based on the value of `isLeft`.
• 4. Return the root node once the tree is fully constructed.
Goal: Ensure that the input list is well-formed and the tree is valid.
Steps:
• The binary tree described by descriptions is valid and does not contain any cycles.
Assumptions:
• The binary tree is guaranteed to be valid and can always be constructed from the descriptions.
• Input: descriptions = [[10, 5, 1], [10, 20, 0], [5, 3, 1], [3, 2, 0]]
• Explanation: In this example, we construct the binary tree where 10 is the root, 5 is the left child of 10, 20 is the right child of 10, 3 is the left child of 5, and 2 is the right child of 3.
• Input: descriptions = [[1, 2, 1], [2, 3, 0], [3, 4, 1]]
• Explanation: In this example, the tree is constructed such that 1 is the root, 2 is the left child of 1, 3 is the right child of 2, and 4 is the left child of 3.
Approach: To solve this problem, we need to build the tree by identifying the root node (which does not appear as a child in any triplet), then iterating over the descriptions to connect the parent and child nodes accordingly. After constructing the tree, we return the root node.
Observations:
• The first step is to identify the root node by checking which node is not a child of any other node.
• Using a map to store each node allows us to easily connect parents and children while building the tree.
Steps:
• 1. Iterate through the descriptions and track all nodes that appear as children.
• 2. Find the root node (the node that does not appear as a child).
• 3. Use a map to create nodes and connect them based on the triplets provided.
• 4. Finally, return the root node.
Empty Inputs:
• There will always be valid input as per the problem constraints.
Large Inputs:
• The approach should be efficient enough to handle the input size up to 10^4 descriptions.
Special Values:
• If there is only one node (parent = child), it will be the root node.
Constraints:
• Ensure that the tree is always valid and does not contain cycles.
TreeNode* createBinaryTree(vector<vector<int>>& desc) {
set<int> s;
for(vector<int> v: desc) {
s.insert(v[0]);
s.insert(v[1]);
}
for(auto v: desc) {
if(s.find(v[1]) != s.end()) {
s.erase(v[1]);
}
}
int root = *s.begin();
// found root
// next create map for nodes
// connect them as given in desc
map<int, TreeNode*> mp;
for(auto v: desc) {
if(mp.find(v[0]) == mp.end()) {
mp[v[0]] = new TreeNode(v[0]);
}
if(mp.find(v[1]) == mp.end()) {
mp[v[1]] = new TreeNode(v[1]);
}
}
for(auto v: desc) {
int paret = v[0];
int child = v[1];
int left = v[2];
if(left) mp[paret]->left = mp[child];
else mp[paret]->right = mp[child];
}
return mp[root];
}
1 : Function Definition
TreeNode* createBinaryTree(vector<vector<int>>& desc) {
This is the function definition, where we pass a 2D vector `desc` that contains the tree's node relationships.
2 : Set Initialization
set<int> s;
Here, a set `s` is initialized to store unique node values from the description.
3 : Iterate over Desc
for(vector<int> v: desc) {
We iterate over each entry in the `desc` vector to process the parent-child relationships.
4 : Insert Parent
s.insert(v[0]);
Insert the parent node value `v[0]` into the set `s`.
5 : Insert Child
s.insert(v[1]);
Insert the child node value `v[1]` into the set `s`.
6 : Second Loop
for(auto v: desc) {
A second iteration over `desc` to refine the node relationships and determine the root.
7 : Find Node in Set
if(s.find(v[1]) != s.end()) {
Check if the child node `v[1]` exists in the set `s`.
8 : Erase Node from Set
s.erase(v[1]);
If the child node is found in the set, remove it from the set, as it's no longer a potential root.
9 : Determine Root
int root = *s.begin();
The root of the tree is the only element left in the set `s`.
10 : Map Initialization
map<int, TreeNode*> mp;
A map `mp` is initialized to store the tree nodes, with their values as keys.
11 : Third Loop
for(auto v: desc) {
Iterate over `desc` again to create the nodes if they don't already exist in the map.
12 : Check and Create Node for Parent
if(mp.find(v[0]) == mp.end()) {
If the parent node `v[0]` is not already in the map, create it.
13 : Add Parent to Map
mp[v[0]] = new TreeNode(v[0]);
Create a new TreeNode for the parent and add it to the map.
14 : Check and Create Node for Child
if(mp.find(v[1]) == mp.end()) {
If the child node `v[1]` is not already in the map, create it.
15 : Add Child to Map
mp[v[1]] = new TreeNode(v[1]);
Create a new TreeNode for the child and add it to the map.
16 : Fourth Loop
for(auto v: desc) {
A loop to establish parent-child connections between the nodes.
17 : Assign Left or Right Child
int paret = v[0];
Assign the parent node value to `paret`.
18 : Assign Left or Right Child
int child = v[1];
Assign the child node value to `child`.
19 : Assign Left or Right Child
int left = v[2];
Assign the left flag value to `left`.
20 : Assign Left Child
if(left) mp[paret]->left = mp[child];
If `left` is true, set the left child of the parent node.
21 : Assign Right Child
else mp[paret]->right = mp[child];
If `left` is false, set the right child of the parent node.
22 : Return Root
return mp[root];
Return the root node, which is the result of the function.
Best Case: O(n), where n is the number of descriptions.
Average Case: O(n), where n is the number of descriptions.
Worst Case: O(n), where n is the number of descriptions.
Description: The time complexity is linear with respect to the number of descriptions, as we only need to process each description once.
Best Case: O(1), when there is only one node.
Worst Case: O(n), where n is the number of nodes in the tree.
Description: The space complexity is linear with respect to the number of nodes in the tree, as we store each node in a map.
| LeetCode Solutions Library / DSA Sheets / Course Catalog |
|---|
comments powered by Disqus