Open In App

Burn the binary tree starting from the target node

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

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


Output

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();


Output

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:

  1. 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.
  2. 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.
  3. 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.
  4. 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}")


Output

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.



Last Updated : 18 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads