Burn the binary tree starting from the target node
Given a binary tree and target node. By giving the fire to the target node and fire starts to spread in a complete tree. The task is to print the sequence of the burning nodes of a binary tree.
Rules for burning the nodes :
- Fire will spread constantly to the connected nodes only.
- Every node takes the same time to burn.
- A node burns only once.
Examples:
Input : 12 / \ 13 10 / \ 14 15 / \ / \ 21 24 22 23 target node = 14 Output : 14 21, 24, 10 15, 12 22, 23, 13 Explanation : First node 14 burns then it gives fire to it's neighbors(21, 24, 10) and so on. This process continues until the whole tree burns. Input : 12 / \ 19 82 / / \ 41 15 95 \ / / \ 2 21 7 16 target node = 41 Output : 41 2, 19 12 82 15, 95 21, 7, 16
Approach :
First search the target node in a binary tree recursively. After finding the target node print it and save its left child(if exist) and right child(if exist) in a queue. and return. Now, get the size of the queue and run while loop. Print elements in the queue.
Below is the implementation of the above approach :
CPP
// C++ implementation to print the sequence // of burning of nodes of a binary tree #include <bits/stdc++.h> using namespace std; // A Tree node struct Node { int key; struct Node *left, *right; }; // Utility function to create a new node Node* newNode( int key) { Node* temp = new Node; temp->key = key; temp->left = temp->right = NULL; return (temp); } // Utility function to print the sequence of burning nodes int burnTreeUtil(Node* root, int target, queue<Node*>& q) { // Base condition if (root == NULL) { return 0; } // Condition to check whether target // node is found or not in a tree if (root->key == target) { cout << root->key << endl; if (root->left != NULL) { q.push(root->left); } if (root->right != NULL) { q.push(root->right); } // Return statements to prevent // further function calls return 1; } int a = burnTreeUtil(root->left, target, q); if (a == 1) { int qsize = q.size(); // Run while loop until size of queue // becomes zero while (qsize--) { Node* temp = q.front(); // Printing of burning nodes cout << temp->key << " , " ; q.pop(); // Check if condition for left subtree if (temp->left != NULL) q.push(temp->left); // Check if condition for right subtree if (temp->right != NULL) q.push(temp->right); } if (root->right != NULL) q.push(root->right); cout << root->key << endl; // Return statement it prevents further // further function call return 1; } int b = burnTreeUtil(root->right, target, q); if (b == 1) { int qsize = q.size(); // Run while loop until size of queue // becomes zero while (qsize--) { Node* temp = q.front(); // Printing of burning nodes cout << temp->key << " , " ; q.pop(); // Check if condition for left subtree if (temp->left != NULL) q.push(temp->left); // Check if condition for left subtree if (temp->right != NULL) q.push(temp->right); } if (root->left != NULL) q.push(root->left); cout << root->key << endl; // Return statement it prevents further // further function call return 1; } } // Function will print the sequence of burning nodes void burnTree(Node* root, int target) { queue<Node*> q; // Function call burnTreeUtil(root, target, q); // While loop runs unless queue becomes empty while (!q.empty()) { int qSize = q.size(); while (qSize > 0) { Node* temp = q.front(); // Printing of burning nodes cout << temp->key; // Insert left child in a queue, if exist if (temp->left != NULL) { q.push(temp->left); } // Insert right child in a queue, if exist if (temp->right != NULL) { q.push(temp->right); } if (q.size() != 1) cout << " , " ; q.pop(); qSize--; } cout << endl; } } // Driver Code int main() { /* 10 / \ 12 13 / \ 14 15 / \ / \ 21 22 23 24 Let us create Binary Tree as shown above */ Node* root = newNode(10); root->left = newNode(12); root->right = newNode(13); root->right->left = newNode(14); root->right->right = newNode(15); root->right->left->left = newNode(21); root->right->left->right = newNode(22); root->right->right->left = newNode(23); root->right->right->right = newNode(24); int targetNode = 14; // Function call burnTree(root, targetNode); return 0; } |
Java
import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; // Tree node class class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode( int val) { this .val = val; } TreeNode( int val, TreeNode left, TreeNode right) { this .val = val; this .left = left; this .right = right; } } class Solution { // function to print the sequence of burning nodes public static int search(TreeNode root, int num, Map<Integer, Set<Integer> > levelOrderMap) { if (root != null ) { // Condition to check whether target // node is found or not in a tree if (root.val == num) { levelOrderStoredInMap(root.left, 1 , levelOrderMap); levelOrderStoredInMap(root.right, 1 , levelOrderMap); // Return statements to prevent // further function calls return 1 ; } int k = search(root.left, num, levelOrderMap); if (k > 0 ) { // store root in map with k storeRootAtK(root, k, levelOrderMap); // store level order for other branch levelOrderStoredInMap(root.right, k + 1 , levelOrderMap); return k + 1 ; } k = search(root.right, num, levelOrderMap); if (k > 0 ) { // store root in map with k storeRootAtK(root, k, levelOrderMap); // store level order for other branch levelOrderStoredInMap(root.left, k + 1 , levelOrderMap); return k + 1 ; } } return - 1 ; // Base condition } public static void levelOrderStoredInMap( TreeNode root, int k, Map<Integer, Set<Integer> > levelOrderMap) { if (root != null ) { storeRootAtK(root, k, levelOrderMap); levelOrderStoredInMap(root.left, k + 1 , levelOrderMap); levelOrderStoredInMap(root.right, k + 1 , levelOrderMap); } } private static void storeRootAtK(TreeNode root, int k, Map<Integer, Set<Integer> > levelOrderMap) { if (levelOrderMap.containsKey(k)) { levelOrderMap.get(k).add(root.val); } else { Set<Integer> set = new HashSet<>(); set.add(root.val); levelOrderMap.put(k, set); } } // Driver Code public static void main(String[] args) { /* 12 / \ 13 10 / \ 14 15 / \ / \ 21 24 22 23 Let us create Binary Tree as shown above */ TreeNode root = new TreeNode( 12 ); root.left = new TreeNode( 13 ); root.right = new TreeNode( 10 ); root.right.left = new TreeNode( 14 ); root.right.right = new TreeNode( 15 ); TreeNode left = root.right.left; TreeNode right = root.right.right; left.left = new TreeNode( 21 ); left.right = new TreeNode( 24 ); right.left = new TreeNode( 22 ); right.right = new TreeNode( 23 ); // Utility map to store the sequence of burning // nodes Map<Integer, Set<Integer> > levelOrderMap = new HashMap<>(); // search node and store the level order from that // node in map search(root, 14 , levelOrderMap); // will print the sequence of burning nodes System.out.println( 14 ); for (Integer level : levelOrderMap.keySet()) { for (Integer val : levelOrderMap.get(level)) { System.out.print(val + " " ); } System.out.println(); } } } // This code is contributed by Niharika Sahai |
Python3
# Python3 implementation to print the sequence # of burning of nodes of a binary tree # A Tree node class Node: def __init__( self , key): self .key = key self .left = None self .right = None # Utility function to create a new node def new_node(key): temp = Node(key) return temp # Utility function to print the sequence of burning nodes def burn_tree_util(root, target, q): # Base condition if root is None : return 0 # Condition to check whether target # node is found or not in a tree if root.key = = target: print (root.key) if root.left is not None : q.append(root.left) if root.right is not None : q.append(root.right) # Return statements to prevent # further function calls return 1 a = burn_tree_util(root.left, target, q) if a = = 1 : q_size = len (q) # Run while loop until size of queue # becomes zero while q_size: temp = q[ 0 ] # Printing of burning nodes print (temp.key, end = ", " ) del q[ 0 ] # Check if condition for left subtree if temp.left is not None : q.append(temp.left) # Check if condition for right subtree if temp.right is not None : q.append(temp.right) q_size - = 1 if root.right is not None : q.append(root.right) print (root.key) # Return statement it prevents further # further function call return 1 b = burn_tree_util(root.right, target, q) if b = = 1 : q_size = len (q) # Run while loop until size of queue # becomes zero while q_size: temp = q[ 0 ] # Printing of burning nodes print (temp.key, end = ", " ) del q[ 0 ] # Check if condition for left subtree if temp.left is not None : q.append(temp.left) # Check if condition for left subtree if temp.right is not None : q.append(temp.right) q_size - = 1 if root.left is not None : q.append(root.left) print (root.key) # Return statement it prevents further # further function call return 1 # Function will print the sequence of burning nodes def burn_tree(root, target): q = [] # Function call burn_tree_util(root, target, q) # While loop runs unless queue becomes empty while q: q_size = len (q) while q_size: temp = q[ 0 ] # Printing of burning nodes print (temp.key, end = "") # Insert left child in a queue, if exist if temp.left is not None : q.append(temp.left) # Insert right child in a queue, if exist if temp.right is not None : q.append(temp.right) if len (q) ! = 1 : print ( ", " , end = "") del q[ 0 ] q_size - = 1 print () # Driver Code if __name__ = = "__main__" : """ 10 / \ 12 13 / \ 14 15 / \ / \ 21 22 23 24 Let us create Binary Tree as shown above """ root = new_node( 10 ) root.left = new_node( 12 ) root.right = new_node( 13 ) root.right.left = new_node( 14 ) root.right.right = new_node( 15 ) root.right.left.left = new_node( 21 ) root.right.left.right = new_node( 22 ) root.right.right.left = new_node( 23 ) root.right.right.right = new_node( 24 ) burn_tree(root, 14 ) # This code is contributed by Potta Lokesh |
C#
// C# implementation using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; public class Gfg { // A Tree node class Node { public int key; public Node left; public Node right; Node() {} public Node( int key) { this .key = key; } Node( int key, Node left, Node right) { this .key = key; this .left = left; this .right = right; } } /*// Utility function to create a new node Node* newNode(int key) { Node* temp = new Node; temp.key = key; temp.left = temp.right = null; return (temp); }*/ // Utility function to print the sequence of burning nodes static int burnTreeUtil(Node root, int target, Queue<Node> q) { // Base condition if (root == null ) { return 0; } // Condition to check whether target // node is found or not in a tree if (root.key == target) { Console.Write(root.key+ "\n" ); if (root.left != null ) { q.Enqueue(root.left); } if (root.right != null ) { q.Enqueue(root.right); } // Return statements to prevent // further function calls return 1; } int a = burnTreeUtil(root.left, target, q); if (a == 1) { int qsize = q.Count; // Run while loop until size of queue // becomes zero while (qsize-->0) { Node temp = q.Peek(); // Printing of burning nodes Console.Write(temp.key + " , " ); q.Dequeue(); // Check if condition for left subtree if (temp.left != null ) q.Enqueue(temp.left); // Check if condition for right subtree if (temp.right != null ) q.Enqueue(temp.right); } if (root.right != null ) q.Enqueue(root.right); Console.Write(root.key+ "\n" ); // Return statement it prevents further // further function call return 1; } int b = burnTreeUtil(root.right, target, q); if (b == 1) { int qsize = q.Count; // Run while loop until size of queue // becomes zero while (qsize-->0) { Node temp = q.Peek(); // Printing of burning nodes Console.Write(temp.key + " , " ); q.Dequeue(); // Check if condition for left subtree if (temp.left != null ) q.Enqueue(temp.left); // Check if condition for left subtree if (temp.right != null ) q.Enqueue(temp.right); } if (root.left != null ) q.Enqueue(root.left); Console.Write(root.key+ "\n" ); // Return statement it prevents further // further function call return 1; } return 0; } // Function will print the sequence of burning nodes static void burnTree(Node root, int target) { Queue<Node> q= new Queue<Node>(); // Function call burnTreeUtil(root, target, q); // While loop runs unless queue becomes empty while (q.Count>0) { int qSize = q.Count; while (qSize > 0) { Node temp = q.Peek(); // Printing of burning nodes Console.Write(temp.key); // Insert left child in a queue, if exist if (temp.left != null ) { q.Enqueue(temp.left); } // Insert right child in a queue, if exist if (temp.right != null ) { q.Enqueue(temp.right); } if (q.Count != 1) Console.Write( " , " ); q.Dequeue(); qSize--; } Console.Write( "\n" ); } } // Driver Code public static void Main( string [] args) { /* 10 / \ 12 13 / \ 14 15 / \ / \ 21 22 23 24 Let us create Binary Tree as shown above */ Node root = new Node(10); root.left = new Node(12); root.right = new Node(13); root.right.left = new Node(14); root.right.right = new Node(15); root.right.left.left = new Node(21); root.right.left.right = new Node(22); root.right.right.left = new Node(23); root.right.right.right = new Node(24); int targetNode = 14; // Function call burnTree(root, targetNode); } } |
Javascript
//This code is an implementation of a binary tree burn algorithm that starts at a node with a specified key value, //burns down the node and its children in a breadth-first order, and outputs the key values of the burned nodes. class Node { //This class represents a node in the binary tree with a key and left and right children. constructor(key) { this .key = key; this .left = null ; this .right = null ; } } //This is the helper function for the main burnTree function. //It starts at the root node, searches for the target node, and stores the path to the target node in the queue 'q'. function burnTreeUtil(root, target, q) { if (!root) { //If the root is null, the target node is not in the tree and the function returns 0. return 0; } if (root.key === target) { console.log(root.key); if (root.left) { q.push(root.left); } if (root.right) { q.push(root.right); } return 1; } let a = burnTreeUtil(root.left, target, q); //The function is recursively called on the left child. //If the target node is found in the left subtree, the key values of the nodes in the path to the target node are added to the queue 'q' if (a === 1) { while (q.length) { let temp = q.shift(); console.log(temp.key + ', ' ); if (temp.left) { q.push(temp.left); } if (temp.right) { q.push(temp.right); } } if (root.right) { q.push(root.right); } console.log(root.key); return 1; } let b = burnTreeUtil(root.right, target, q); //The function is recursively called on the right child. //If the target node is found in the right subtree, the key values of the nodes in the path to the target node are added to the queue 'q'. if (b === 1) { while (q.length) { let temp = q.shift(); console.log(temp.key + ', ' ); if (temp.left) { q.push(temp.left); } if (temp.right) { q.push(temp.right); } } if (root.left) { q.push(root.left); } console.log(root.key); return 1; } } function burnTree(root, target) { let q = []; burnTreeUtil(root, target, q); while (q.length) { let qSize = q.length; while (qSize > 0) { let temp = q.shift(); console.log(temp.key); if (temp.left) { q.push(temp.left); } if (temp.right) { q.push(temp.right); } if (q.length !== 1) { console.log( ', ' ); } qSize--; } console.log( '\n' ); } } let root = new Node(10); root.left = new Node(12); root.right = new Node(13); root.right.left = new Node(14); root.right.right = new Node(15); root.right.left.left = new Node(21); root.right.left.right = new Node(22); root.right.right.left = new Node(23); root.right.right.right = new Node(24); //call burnTree(root, 14); //This code is contributed by Abhijit Ghosh |
14 21 , 22 , 13 15 , 10 23 , 24 , 12
Time complexity :- O(N^2)
Space complexity :- O(N)
Another Approach: Convert the tree into undirected graph and print its level order traversal
- Build a undirected graph using Treenodes as vertices, and the parent-child relation as edges
- Do BFS with source vertex as a target.
C++
// C++ program to implement the above approach #include <bits/stdc++.h> using namespace std; struct TreeNode { int val; TreeNode* left; TreeNode* right; }; TreeNode* newNode( int key) { TreeNode* temp = new TreeNode; temp->val = key; temp->left = temp->right = NULL; return (temp); } unordered_map<TreeNode*, vector<TreeNode*> > map_; // build undirected graph void buildMap(TreeNode* node, TreeNode* parent) { if (node == NULL) return ; if (map_.find(node) == map_.end()) { vector<TreeNode*> vec; map_[node] = vec; if (parent != NULL) { map_[node].push_back(parent); map_[parent].push_back(node); } buildMap(node->left, node); buildMap(node->right, node); } } void burnTree(TreeNode* root, TreeNode* target) { vector< int > res; if (root == NULL) return ; buildMap(root, NULL); if (map_.find(target) == map_.end()) { cout << "Target Not found" << endl; return ; } unordered_set<TreeNode*> visited; // BFS traversal queue<TreeNode*> q; q.push(target); visited.insert(target); while (!q.empty()) { int size = q.size(); for ( int i = 0; i < size; i++) { TreeNode* node = q.front(); q.pop(); cout << node->val << " " ; for ( auto next : map_[node]) { if (visited.find(next) != visited.end()) continue ; visited.insert(next); q.push(next); } } cout << endl; } } int main() { TreeNode* root = newNode(12); root->left = newNode(13); root->right = newNode(10); root->right->left = newNode(14); root->right->right = newNode(15); TreeNode* left = root->right->left; TreeNode* right = root->right->right; left->left = newNode(21); left->right = newNode(24); right->left = newNode(22); right->right = newNode(23); // target Node value is 14 burnTree(root, left); cout << endl; } // This code is contributed by Abhijeet Kumar(abhijeet_19403) |
Java
import java.io.*; import java.util.*; public class GFG { /*package whatever //do not write package name here */ static class TreeNode { int val; TreeNode left; TreeNode right; TreeNode() {} TreeNode( int val) { this .val = val; } TreeNode( int val, TreeNode left, TreeNode right) { this .val = val; this .left = left; this .right = right; } } static Map<TreeNode, List<TreeNode>> map = new HashMap<>(); public static void main (String[] args) { TreeNode root = new TreeNode( 12 ); root.left = new TreeNode( 13 ); root.right = new TreeNode( 10 ); root.right.left = new TreeNode( 14 ); root.right.right = new TreeNode( 15 ); TreeNode left = root.right.left; TreeNode right = root.right.right; left.left = new TreeNode( 21 ); left.right = new TreeNode( 24 ); right.left = new TreeNode( 22 ); right.right = new TreeNode( 23 ); // target Node value is 14 burnTree(root,left); System.out.println(); } private static void burnTree(TreeNode root, TreeNode target) { List<Integer> res = new ArrayList<Integer> (); if (root == null ) return ; buildMap(root, null ); if (!map.containsKey(target)) { System.out.println( "Target Not found" ); return ; } Set<TreeNode> visited = new HashSet<TreeNode>(); //BFS traversal Queue<TreeNode> q = new LinkedList<TreeNode>(); q.add(target); visited.add(target); while (!q.isEmpty()) { int size = q.size(); for ( int i = 0 ; i < size; i++) { TreeNode node = q.poll(); System.out.print(node.val+ " " ); for (TreeNode next : map.get(node)) { if (visited.contains(next)) continue ; visited.add(next); q.add(next); } } System.out.println(); } } // build undirected graph private static void buildMap(TreeNode node, TreeNode parent) { if (node == null ) return ; if (!map.containsKey(node)) { map.put(node, new ArrayList<TreeNode>()); if (parent != null ) { map.get(node).add(parent); map.get(parent).add(node) ; } buildMap(node.left, node); buildMap(node.right, node); } } } |
C#
//C# program to print the sequence // of burning of nodes of a binary tree using System; using System.Collections.Generic; using System.Linq; public class GFG{ // Tree node class public class TreeNode { public int val; public TreeNode left; public TreeNode right; TreeNode() {} public TreeNode( int val) { this .val = val; } TreeNode( int val, TreeNode left, TreeNode right) { this .val = val; this .left = left; this .right = right; } } static Dictionary <TreeNode, List<TreeNode>> map = new Dictionary <TreeNode, List<TreeNode>>(); static public void Main (){ TreeNode root = new TreeNode(12); root.left = new TreeNode(13); root.right = new TreeNode(10); root.right.left = new TreeNode(14); root.right.right = new TreeNode(15); TreeNode left = root.right.left; TreeNode right = root.right.right; left.left = new TreeNode(21); left.right = new TreeNode(24); right.left = new TreeNode(22); right.right = new TreeNode(23); // target Node value is 14 burnTree(root,left); Console.Write( "\n" ); } static public void burnTree(TreeNode root, TreeNode target){ //List<int> res = new List<int> (); if (root == null ) return ; buildMap(root, null ); if (!map.ContainsKey(target)) { Console.Write( "Target Not found" ); return ; } HashSet<TreeNode> visited = new HashSet<TreeNode>(); //BFS traversal Queue<TreeNode> q = new Queue<TreeNode>(); q.Enqueue(target); visited.Add(target); while (q.Count()!=0) { int size = q.Count(); for ( int i = 0; i < size; i++) { TreeNode node = q.Dequeue(); Console.Write(node.val+ " " ); foreach (TreeNode next in map[node]) { if (visited.Contains(next)) continue ; visited.Add(next); q.Enqueue(next); } } Console.Write( "\n" ); } } // build undirected graph static public void buildMap(TreeNode node, TreeNode parent){ if (node == null ) return ; if (!map.ContainsKey(node)){ map[node] = new List<TreeNode>(); if (parent != null ){ map[node].Add(parent); map[parent].Add(node); } buildMap(node.left, node); buildMap(node.right, node); } } } // This code is contributed by shruti456rawal |
Python3
#Python program for the above approach from collections import defaultdict # A Tree node class TreeNode: def __init__( self , val = 0 , left = None , right = None ): self .val = val self .left = left self .right = right # Function to build the undirected graph def build_map(node, parent, graph): if node is None : return if node not in graph: graph[node] = [] if parent is not None : graph[node].append(parent) graph[parent].append(node) build_map(node.left, node, graph) build_map(node.right, node, graph) # Function to burn the tree def burn_tree(root, target): # Map to store the nodes of the tree graph = defaultdict( list ) build_map(root, None , graph) if target not in graph: print ( "Target Not found" ) return visited = set () queue = [] queue.append(target) visited.add(target) while queue: size = len (queue) for i in range (size): node = queue.pop( 0 ) print (node.val, end = " " ) for next in graph[node]: if next in visited: continue visited.add( next ) queue.append( next ) print () #Driver code root = TreeNode( 12 ) root.left = TreeNode( 13 ) root.right = TreeNode( 10 ) root.right.left = TreeNode( 14 ) root.right.right = TreeNode( 15 ) left = root.right.left right = root.right.right left.left = TreeNode( 21 ) left.right = TreeNode( 24 ) right.left = TreeNode( 22 ) right.right = TreeNode( 23 ) # target Node value is 14 burn_tree(root, left) #This code is contributed by Potta Lokesh |
Javascript
// Define a class TreeNode with three properties class TreeNode { constructor(val, left = null , right = null ) { this .val = val; this .left = left; this .right = right; } } // Initialize a map to store nodes and their children let map = new Map(); // Define a function to construct the tree and call burnTree function main() { let root = new TreeNode(12); root.left = new TreeNode(13); root.right = new TreeNode(10); root.right.left = new TreeNode(14); root.right.right = new TreeNode(15); let left = root.right.left; let right = root.right.right; left.left = new TreeNode(21); left.right = new TreeNode(24); right.left = new TreeNode(22); right.right = new TreeNode(23); let target = root.right.left; burnTree(root, target); } // Define a function to burn the tree starting from the target node function burnTree(root, target) { let res = []; if (!root) return ; buildMap(root, null ); if (!map.has(target)) { console.log( "Target not found" ); return ; } let visited = new Set(); let q = [target]; visited.add(target); while (q.length > 0) { let size = q.length; for (let i = 0; i < size; i++) { let node = q.shift(); res.push(node.val); for (let next of map.get(node)) { if (visited.has(next)) continue ; visited.add(next); q.push(next); } } console.log(res.join( " " )); res = []; } } // Define a function to build the undirected graph function buildMap(node, parent) { if (!node) return ; if (!map.has(node)) { map.set(node, []); if (parent) { map.get(node).push(parent); map.get(parent).push(node); } buildMap(node.left, node); buildMap(node.right, node); } } // Call the main function main(); |
14 10 21 24 12 15 13 22 23
Time Complexity: O(n), where n is the number of nodes in the binary tree. We need to traverse all the nodes in the binary tree to build the map and perform BFS traversal.
Space Complexity: O(n), where n is the number of nodes in the binary tree. We need to store all the nodes in the unordered_map and the queue used in BFS traversal.
An approach using DFS:
The idea is to do an inorder traversal of the tree, and return some information of how far the current node is from the target node. For this, we check if we found the target in each recursive iteration.
Follow the steps below to implement the above idea:
- If we find the target node, then we know that we have to start from 1 for all the children of the sub-tree rooted at this node. In addition, we return 1, meaning that we found the target value.
- After we have checked for condition 1, we then recursively call the algorithm for left subtree and right subtree from the current node. By definition, only one of these recursive calls can return 1, as the target node can be present only in the left subtree or the right subtree of the current node.
- If we get 1 from the left subtree, it means that the target node is present in the left subtree, so we recursively call the algorithm again for right subtree (the maximum value for the left subtree is taken care of in step 1). Conversely, if we get 1 from right subtree, we recursively call the algorithm for left subtree.
- At each step of the algorithm, we maintain the maximum value in an answer variable, and at the end, we return the answer.
Please refer to the code below for a detailed C++ solution.
C++
#include <bits/stdc++.h> using namespace std; struct Node { int data; Node* left; Node* right; }; Node* newNode( int key) { Node* temp = new Node; temp->data = key; temp->left = temp->right = NULL; return (temp); } int findMinTime(Node* root, int target, int level, unordered_map< int , vector< int > >& ans, int consider) { if (root == NULL) return -1; if (consider == 1) { ans[level].push_back(root->data); } if (root->data == target) { ans[0].push_back(root->data); findMinTime(root->left, target, 1, ans, 1); findMinTime(root->right, target, 1, ans, 1); return 1; } int left = findMinTime(root->left, target, level + 1, ans, consider); int right = findMinTime(root->right, target, level + 1, ans, consider); if (left != -1) { ans[left].push_back(root->data); findMinTime(root->right, target, left + 1, ans, 1); return left + 1; } if (right != -1) { ans[right].push_back(root->data); findMinTime(root->left, target, right + 1, ans, 1); return right + 1; } return -1; } unordered_map< int , vector< int > > minTime(Node* root, int target) { unordered_map< int , vector< int > > ans; findMinTime(root, target, 0, ans, 0); return ans; } int main() { Node* root = newNode(10); root->left = newNode(12); root->right = newNode(13); root->right->left = newNode(14); root->right->right = newNode(15); root->right->left->left = newNode(21); root->right->left->right = newNode(22); root->right->right->left = newNode(23); root->right->right->right = newNode(24); int targetNode = 14; unordered_map< int , vector< int > > answer = minTime(root, targetNode); for ( auto it = answer.begin(); it != answer.end(); it++) { cout << "Nodes burnt at stage " << it->first << " are " ; for ( int i = 0; i < it->second.size(); i++) { cout << it->second[i] << " " ; } cout << endl; } return 0; } // This code is contributed by "Dilraj Singh" |
Java
import java.util.*; public class Main { // define the class of a Node static class Node { int data; Node left; Node right; } // create a new Node with a given key static Node newNode( int key) { Node temp = new Node(); temp.data = key; temp.left = temp.right = null ; return temp; } // find the minimum time to burn the tree from target // node to all other nodes static int findMinTime(Node root, int target, int level, HashMap<Integer, List<Integer> > ans, int consider) { // if the root is null, return -1 if (root == null ) return - 1 ; // if consider is 1, push the root node data to ans // at the current level if (consider == 1 ) { ans.computeIfAbsent(level, k -> new ArrayList<>()) .add(root.data); } // if the root node is the target node, add it to // ans at level 0 and recursively call findMinTime // on its left and right subtrees if (root.data == target) { ans.computeIfAbsent( 0 , k -> new ArrayList<>()) .add(root.data); findMinTime(root.left, target, 1 , ans, 1 ); findMinTime(root.right, target, 1 , ans, 1 ); return 1 ; } // recursively call findMinTime on the left and // right subtrees and store their return values int left = findMinTime(root.left, target, level + 1 , ans, consider); int right = findMinTime(root.right, target, level + 1 , ans, consider); // if left subtree has the target node, push the // root node data to ans at the level of the left // subtree + 1 and recursively call findMinTime on // the right subtree if (left != - 1 ) { ans.computeIfAbsent(left, k -> new ArrayList<>()) .add(root.data); findMinTime(root.right, target, left + 1 , ans, 1 ); return left + 1 ; } // if right subtree has the target node, push the // root node data to ans at the level of the right // subtree + 1 and recursively call findMinTime on // the left subtree if (right != - 1 ) { ans.computeIfAbsent(right, k -> new ArrayList<>()) .add(root.data); findMinTime(root.left, target, right + 1 , ans, 1 ); return right + 1 ; } // if the target node is not found in the left or // right subtrees, return -1 return - 1 ; } // return a HashMap with levels as keys and a List of // nodes burnt at each level as values static HashMap<Integer, List<Integer> > minTime(Node root, int target) { HashMap<Integer, List<Integer> > ans = new HashMap<>(); findMinTime(root, target, 0 , ans, 0 ); return ans; } public static void main(String[] args) { Node root = newNode( 10 ); root.left = newNode( 12 ); root.right = newNode( 13 ); root.right.left = newNode( 14 ); root.right.right = newNode( 15 ); root.right.left.left = newNode( 21 ); root.right.left.right = newNode( 22 ); root.right.right.left = newNode( 23 ); root.right.right.right = newNode( 24 ); int targetNode = 14 ; HashMap<Integer, List<Integer> > answer = minTime(root, targetNode); for (Map.Entry<Integer, List<Integer> > entry : answer.entrySet()) { System.out.print( "Nodes burnt at stage " + entry.getKey() + " are " ); List<Integer> nodeValues = entry.getValue(); for ( int i = 0 ; i < nodeValues.size(); i++) { System.out.print(nodeValues.get(i) + " " ); } System.out.println(); } } } |
C#
using System; using System.Collections; using System.Collections.Generic; using System.Linq; class Node { public int data; public Node left; public Node right; public Node( int val){ data = val; left = null ; right = null ; } } class HelloWorld { public static int findMinTime(Node root, int target, int level, Dictionary< int , List< int >> ans, int consider) { if (root == null ) return -1; if (consider == 1) { if (ans.ContainsKey(level) == false ){ ans.Add(level, new List< int >()); } ans[level].Add(root.data); } if (root.data == target) { if (ans.ContainsKey(0) == false ){ ans.Add(0, new List< int >()); } ans[0].Add(root.data); findMinTime(root.left, target, 1, ans, 1); findMinTime(root.right, target, 1, ans, 1); return 1; } int left = findMinTime(root.left, target, level + 1, ans, consider); int right = findMinTime(root.right, target, level + 1, ans, consider); if (left != -1) { if (ans.ContainsKey(left) == false ){ ans.Add(left, new List< int >()); } ans[left].Add(root.data); findMinTime(root.right, target, left + 1, ans, 1); return left + 1; } if (right != -1) { if (ans.ContainsKey(right) == false ){ ans.Add(right, new List< int >()); } ans[right].Add(root.data); findMinTime(root.left, target, right + 1, ans, 1); return right + 1; } return -1; } public static Dictionary< int , List< int >> minTime(Node root, int target) { Dictionary< int , List< int >> ans = new Dictionary< int , List< int >>(); int res = findMinTime(root, target, 0, ans, 0); return ans; } static void Main() { Node root = new Node(10); root.left = new Node(12); root.right = new Node(13); root.right.left = new Node(14); root.right.right = new Node(15); root.right.left.left = new Node(21); root.right.left.right = new Node(22); root.right.right.left = new Node(23); root.right.right.right = new Node(24); int targetNode = 14; Dictionary< int , List< int >> answer = minTime(root, targetNode); foreach (KeyValuePair< int , List< int >> it in answer.Reverse()) { Console.Write( "Nodes burnt at stage " + it.Key + " are " ); foreach ( var i in it.Value){ Console.Write(i + " " ); } Console.WriteLine(); } } } // The code is contributed by Nidhi goel |
Javascript
// javascript code addition // define the class of a Node class Node { constructor(){ this .data = 0; this .left = null ; this .right = null ; } } // create a new Node with a given key function newNode(key) { let temp = new Node(); temp.data = key; temp.left = temp.right = null ; return temp; } // find the minimum time to burn the tree from target // node to all other nodes function findMinTime(root, target, level, ans, consider) { // if the root is null, return -1 if (root == null ) return -1; // if consider is 1, push the root node data to ans // at the current level if (consider == 1 ) { if (ans.has(level) == false ){ let temp = new Array(); temp.push(root.data); ans.set(level, temp); } else { let temp = ans.get(level); temp.push(root.data); ans.set(level, temp); } } // if the root node is the target node, add it to // ans at level 0 and recursively call findMinTime // on its left and right subtrees if (root.data == target && ans.has(0) == false ) { if (ans.has(0) == false ){ let temp = new Array(); temp.push(root.data); ans.set(0, temp); } else { let temp = ans.get(0); temp.push(root.data); ans.set(0, temp); } findMinTime(root.left, target, 1, ans, 1); findMinTime(root.right, target, 1, ans, 1); return 1; } // recursively call findMinTime on the left and // right subtrees and store their return values let left = findMinTime(root.left, target, level + 1, ans, consider); let right = findMinTime(root.right, target, level + 1, ans, consider); // if left subtree has the target node, push the // root node data to ans at the level of the left // subtree + 1 and recursively call findMinTime on // the right subtree if (left != -1) { if (ans.has(left) == false ){ let temp = new Array(); temp.push(root.data); ans.set(left, temp); } else { let temp = ans.get(left); temp.push(root.data); ans.set(left, temp); } findMinTime(root.right, target, left + 1, ans, 1); return left + 1; } // if right subtree has the target node, push the // root node data to ans at the level of the right // subtree + 1 and recursively call findMinTime on // the left subtree if (right != -1) { if (ans.has(right) == false ){ let temp = new Array(); temp.push(root.data); ans.set(right, temp); } else { let temp = ans.get(right); temp.push(root.data); ans.set(right, temp); } findMinTime(root.left, target, right + 1, ans,1); return right + 1; } // if the target node is not found in the left or // right subtrees, return -1 return -1; } // return a HashMap with levels as keys and a List of // nodes burnt at each level as values function minTime(root, target) { let ans = new Map(); findMinTime(root, target, 0, ans, 0); return ans; } let root = newNode(10); root.left = newNode(12); root.right = newNode(13); root.right.left = newNode(14); root.right.right = newNode(15); root.right.left.left = newNode(21); root.right.left.right = newNode(22); root.right.right.left = newNode(23); root.right.right.right = newNode(24); let targetNode = 14; let answer = minTime(root, targetNode); for (let [key, value] of answer) { let temp = "" ; for (let i = 0; i < value.length; i++){ temp = temp + value[i] + " " ; } console.log( "Nodes burnt at stage " + key + " are " + temp); } // The code is contributed by Nidhi goel. |
Python3
from typing import List , Dict # Define a Node class class Node: def __init__( self , data): self .data = data self .left = None self .right = None # Define a function to create a new Node def newNode(key: int ) - > Node: temp = Node(key) temp.left = temp.right = None return temp # Define a recursive function to find minimum time required to burn the binary tree def findMinTime(root: Node, target: int , level: int , ans: Dict [ int , List [ int ]], consider: int ) - > int : # Base case: If the node is None, return -1 if root is None : return - 1 # If the current node is the target node or we need to consider it, # add it to the corresponding level of the answer dictionary if consider = = 1 : ans[level].append(root.data) # If the current node is the target node, start burning the left and right subtrees if root.data = = target: ans[ 0 ].append(root.data) findMinTime(root.left, target, 1 , ans, 1 ) findMinTime(root.right, target, 1 , ans, 1 ) return 1 # Recursively find the minimum time required to burn the left and right subtrees left = findMinTime(root.left, target, level + 1 , ans, consider) right = findMinTime(root.right, target, level + 1 , ans, consider) # If the left subtree is not burnt yet, burn it and add the current node to the answer dictionary if left ! = - 1 : ans[left].append(root.data) findMinTime(root.right, target, left + 1 , ans, 1 ) return left + 1 # If the right subtree is not burnt yet, burn it and add the current node to the answer dictionary if right ! = - 1 : ans[right].append(root.data) findMinTime(root.left, target, right + 1 , ans, 1 ) return right + 1 # If both subtrees are already burnt, return -1 return - 1 # Define a function to find the minimum time required to burn the binary tree def minTime(root: Node, target: int ) - > Dict [ int , List [ int ]]: # Initialize an empty dictionary to store the answer ans = {i: [] for i in range ( 100 )} # Call the recursive function to find the minimum time findMinTime(root, target, 0 , ans, 0 ) # Return the answer dictionary return ans # Driver code if __name__ = = '__main__' : # Create the binary tree root = newNode( 10 ) root.left = newNode( 12 ) root.right = newNode( 13 ) root.right.left = newNode( 14 ) root.right.right = newNode( 15 ) root.right.left.left = newNode( 21 ) root.right.left.right = newNode( 22 ) root.right.right.left = newNode( 23 ) root.right.right.right = newNode( 24 ) # Set the target node targetNode = 14 # Call the function to find the minimum time required to burn the binary tree answer = minTime(root, targetNode) # Print the answer for key, value in answer.items(): if not value: break print (f "Nodes burnt at stage {key} are {value}" ) |
Nodes burnt at stage 3 are 23 24 12 Nodes burnt at stage 2 are 15 10 Nodes burnt at stage 1 are 21 22 13 Nodes burnt at stage 0 are 14
The time complexity of the above code is O(n), because the code performs a single traversal of the tree. At each node, it takes constant time to update the unordered_map and perform the recursive calls. Therefore, the time complexity is linear in the number of nodes in the tree.
The Auxiliary Space of the above code is O(n), where n is the number of nodes in the tree. This is because the code uses an unordered_map to store the nodes burnt at each stage, and the size of the map increases linearly with the number of nodes in the tree.
Please Login to comment...