Minimum time to burn a Tree starting from a Leaf node

13 Jul, 2021
Given a binary tree and a leaf node from this tree. It is known that in 1s all nodes connected to a given node (left child, right child and parent) get burned in 1 second. Then all the nodes which are connected through one intermediate get burned in 2 seconds, and so on. The task is to find the minimum time required to burn the complete binary tree.Examples:  
Input : 
            1
       /       \
      2          3
    /  \          \
   4    5          6
      /   \         \
     7     8         9
                      \
                       10
Leaf = 8
Output : 7
Initially 8 is set to fire at 0th sec.
            1
       /       \
      2          3
    /  \          \
   4    5          6
      /   \         \
     7     F         9
                      \
                       10
After 1s: 5 is set to fire.
            1
       /       \
      2          3
    /  \          \
   4    F          6
      /   \         \
     7     F         9
                      \
                       10
After 2s: 2, 7 are set to fire.
            1
       /       \
      F          3
    /  \          \
   4    F          6
      /   \         \
     F     F         9
                      \
                       10
After 3s: 4, 1 are set to fire.
            F
       /       \
      F          3
    /  \          \
   F    F          6
      /   \         \
     F     F         9
                      \
                       10
After 4s: 3 is set to fire.
            F
       /       \
      F          F
    /  \          \
   F    F          6
      /   \         \
     F     F         9
                      \
                       10
After 5s: 6 is set to fire.
            F
       /       \
      F          F
    /  \          \
   F    F          F
      /   \         \
     F     F         9
                      \
                       10
After 6s: 9 is set to fire.
            F
       /       \
      F          F
    /  \          \
   F    F          F
      /   \         \
     F     F         F
                      \
                       10
After 7s: 10 is set to fire.
            F
       /       \
      F          F
    /  \          \
   F    F          F
      /   \         \
     F     F         F
                      \
                       F
It takes 7s to burn the complete tree.
 
The idea is to store additional information for every node:  
Depth of left subtree.
Depth of right subtree.
The time required for the fire to reach the current node starting from the first leaf node burned.
A boolean variable to check if the initial burnt node is in the tree rooted under current node.
Before moving ahead with the approach let’s take a look at the tree below:  
              1
          /      \          
       2            3
     /   \         /
    4     5       6 
   /     / \
  8     9   10
       /
      11
In the above tree, if we set the leaf node 11 at fire.  
In 1s, the fire will reach node 9.In 2s, the fire will reach node 5.In 3rd second, the fire will reach node 2 and 10. Here comes an observation: In 2s fire reached node 5. For node 5, the initial burned leaf is in it’s left subtree, so the time taken to burn right subtree will be the height of the right subtree which is 1. Therefore, fire reaches to node 10 in (2+1) = 3s.Again, for the node 2. Fire reached to node 2 in 3s from right subtree. Therefore, time taken to burn left subtree will be it’s height.  
In 1s, the fire will reach node 9.
In 2s, the fire will reach node 5.
In 3rd second, the fire will reach node 2 and 10. Here comes an observation: In 2s fire reached node 5. For node 5, the initial burned leaf is in it’s left subtree, so the time taken to burn right subtree will be the height of the right subtree which is 1. Therefore, fire reaches to node 10 in (2+1) = 3s.Again, for the node 2. Fire reached to node 2 in 3s from right subtree. Therefore, time taken to burn left subtree will be it’s height.  
In 2s fire reached node 5. For node 5, the initial burned leaf is in it’s left subtree, so the time taken to burn right subtree will be the height of the right subtree which is 1. Therefore, fire reaches to node 10 in (2+1) = 3s.
Again, for the node 2. Fire reached to node 2 in 3s from right subtree. Therefore, time taken to burn left subtree will be it’s height.  
So the solution is to apply recursion and for every node calculate the below-required values:  
Left Depth.
Right Depth.
The time required for fire to reach the current node.
Is the current subtree contains initial burnt leaf node.
So, for the minimum time required to burn any subtree will be:  
The time required for fire to reach the root node from initial burnt leaf + depth of the opposite side  
Therefore, to find time required to burn the complete tree, we need to calculate the above value for every node, and take maximum of that value.  
ans = max(ans, (time required for fire to reach current node + depth of other subtree))  
Below is the implementation of the above approach: 
C++
Java
Python3
C#
// C++ program to find minimum time required// to burn the binary tree completely #include <bits/stdc++.h>using namespace std; // Tree Nodestruct Node {    int data;    Node* left;    Node* right;     Node()    {        left = NULL;        right = NULL;    }}; // Utility function to create a new NodeNode* newNode(int val){    Node* temp = new Node;     temp->data = val;     return temp;} /*        ***********ADDITIONAL INFO*************        lDepth - maximum height of left subtree        rDepth - maximum height of right subtree        contains - stores true if tree rooted at current           node contains the first burnt node time - time to reach           fire from the initially burnt leaf node to this node*/struct Info {    int lDepth;    int rDepth;    bool contains;     int time;     Info()    {        lDepth = rDepth = 0;        contains = false;         time = -1;    }}; /*        Function to calculate time required to burn        tree completely         node - address of current node        info - extra information about current node        target - node that is fired        res - stores the result*/Info calcTime(Node* node, Info& info, int target, int& res){     // Base case: if root is null    if (node == NULL) {        return info;    }     // If current node is leaf    if (node->left == NULL && node->right == NULL) {         // If current node is the first burnt node        if (node->data == target) {            info.contains = true;            info.time = 0;        }        return info;    }     // Information about left child of root    Info leftInfo;    calcTime(node->left, leftInfo, target, res);     // Information about right child of root    Info rightInfo;    calcTime(node->right, rightInfo, target, res);     // If left subtree contains the fired node then    // time required to reach fire to current node    // will be (1 + time required for left child)    info.time = (node->left && leftInfo.contains)                    ? (leftInfo.time + 1)                    : -1;     // If right subtree contains the fired node then    // time required to reach fire to current node    // will be (1 + time required for right child)    if (info.time == -1)        info.time = (node->right && rightInfo.contains)                        ? (rightInfo.time + 1)                        : -1;     // Storing(true or false) if the tree rooted at    // current node contains the fired node    info.contains        = ((node->left && leftInfo.contains)           || (node->right && rightInfo.contains));     // Calculate the maximum depth of left subtree    info.lDepth        = !(node->left)              ? 0              : (1 + max(leftInfo.lDepth, leftInfo.rDepth));     // Calculate the maximum depth of right subtree    info.rDepth        = !(node->right)              ? 0              : (1                 + max(rightInfo.lDepth, rightInfo.rDepth));     // Calculating answer    if (info.contains) {        // If left subtree exists and        // it contains the fired node        if (node->left && leftInfo.contains) {            // calculate result            res = max(res, info.time + info.rDepth);        }         // If right subtree exists and it        // contains the fired node        if (node->right && rightInfo.contains) {            // calculate result            res = max(res, info.time + info.lDepth);        }    }} // Driver function to calculate minimum// time requiredint minTime(Node* root, int target){    int res = 0;    Info info;     calcTime(root, info, target, res);     return res;} // Driver Codeint main(){    Node* root = newNode(1);    root->left = newNode(2);    root->right = newNode(3);    root->left->left = newNode(4);    root->left->right = newNode(5);    root->right->left = newNode(6);    root->left->left->left = newNode(8);    root->left->right->left = newNode(9);    root->left->right->right = newNode(10);    root->left->right->left->left = newNode(11);     // target node is 8    int target = 11;     cout << minTime(root, target);     return 0;}
// Java program to find minimum time required// to burn the binary tree completely public class GFG {     // Tree Node    static class Node {        int data;        Node left, right;         Node(int data)        {            this.data = data;            this.left = null;            this.right = null;        }    }     /*        ***********ADDITIONAL INFO*************        lDepth - maximum height of left subtree        rDepth - maximum height of right subtree        contains - stores true if tree rooted at current node                contains the first burnt node        time - time to reach fire from the initially burnt leaf            node to this node    */    static class Data {        int leftDepth, rightDepth, time;        boolean contains;         Data()        {            contains = false;            leftDepth = rightDepth = 0;            time = -1;        }    }     /*        Function to calculate time required to burn        tree completely                 node - address of current node        info - extra information about current node        target - node that is fired        res - stores the result    */    public static void getResult(Node node, Data data, int target)    {         // Base case: if root is null        if (node == null) {            return;        }         // If current node is leaf        if (node.left == null && node.right == null) {             // If current node is the first burnt node            if (node.data == target) {                data.contains = true;                data.time = 0;            }            return;        }         // Information about left child        Data leftData = new Data();        getResult(node.left, leftData, target);         // Information about right child        Data rightData = new Data();        getResult(node.right, rightData, target);         // If left subtree contains the fired node then        // time required to reach fire to current node        // will be (1 + time required for left child)        data.time = (leftData.contains) ? (leftData.time + 1) : -1;         // If right subtree contains the fired node then        // time required to reach fire to current node        // will be (1 + time required for right child)        if (data.time == -1)            data.time = (rightData.contains) ? (rightData.time + 1) : -1;         // Storing(true or false) if the tree rooted at        // current node contains the fired node        data.contains = (leftData.contains || rightData.contains);         // Calculate the maximum depth of left subtree        data.leftDepth = (node.left == null) ? 0 : (1 + Math.max(leftData.leftDepth, leftData.rightDepth));         // Calculate the maximum depth of right subtree        data.rightDepth = (node.right == null) ? 0 : (1 + Math.max(rightData.leftDepth, rightData.rightDepth));         // Calculating answer        if (data.contains) {             // If left subtree exists and            // it contains the fired node            if (leftData.contains) {                 // calculate result                res = Math.max(res, data.time + data.rightDepth);            }             // If right subtree exists and it            // contains the fired node            if (rightData.contains) {                 // calculate result                res = Math.max(res, data.time + data.leftDepth);            }        }    }     // To store the result    public static int res;     // Driver Code    public static void main(String args[])    {         Node root = new Node(1);        root.left = new Node(2);        root.right = new Node(3);        root.left.left = new Node(4);        root.left.right = new Node(5);        root.right.left = new Node(6);        root.left.left.left = new Node(8);        root.left.right.left = new Node(9);        root.left.right.right = new Node(10);        root.left.right.left.left = new Node(11);         int target = 11;         res = 0;        getResult(root, new Data(), target);        System.out.println(res);    }}
# Python program to find minimum time required# to burn the binary tree completely # Definition for a  binary tree node  class TreeNode:    def __init__(self, x):        self.val = x        self.left = None        self.right = None  '''    ***********ADDITIONAL INFO*************    lDepth - maximum height of left subtree    rDepth - maximum height of right subtree    contains - stores true if tree rooted at current node               contains the first burnt node    time - time to reach fire from the initially burnt leaf           node to this node'''  class Info:    def __init__(self):        self.lDepth = 0        self.rDepth = 0        self.contains = False        self.time = -1  class Solution:    # Class Variable    res = 0     '''        Function to calculate time required to burn        tree completely         node - address of current node        info - extra information about current node        target - node that is fired        res - stores the result    '''     def calcTime(self, node, info, target):        # Base case: if root is null        if node == None:            return info         if node.left == None and node.right == None:            # If current node is the first burnt node            if node.val == target:                info.contains = True                info.time = 0            return info         # Information about left child of root        leftInfo = Info()        leftInfo = self.calcTime(node.left, leftInfo, target)         # Information about right child of root        rightInfo = Info()        rightInfo = self.calcTime(node.right, rightInfo, target)         # If left subtree contains the fired node then        # time required to reach fire to current node        # will be (1 + time required for left child)        info.time = leftInfo.time + \            1 if (node.left and leftInfo.contains) else -1         # If right subtree contains the fired node then        # time required to reach fire to current node        # will be (1 + time required for right child)        if info.time == -1:            info.time = rightInfo.time + \                1 if (node.right and rightInfo.contains) else -1         # Storing(true or false) if the tree rooted at        # current node contains the fired node        info.contains = (node.left and leftInfo.contains) or (            node.right and rightInfo.contains)         # Calculate the maximum depth of left subtree        info.lDepth = 0 if (not node.left) else (            1+max(leftInfo.lDepth, leftInfo.rDepth))         # Calculate the maximum depth of right subtree        info.rDepth = 0 if (not node.right) else (            1+max(rightInfo.lDepth, rightInfo.rDepth))         # Calculating answer        if info.contains:            # If left subtree exists and            # it contains the fired node            if node.left and leftInfo.contains:                # calculate result                self.res = max(self.res, info.time+info.rDepth)             # If right subtree exists and it            # contains the fired node            if node.right and rightInfo.contains:                # calculate result                self.res = max(self.res, info.time+info.lDepth)         return info     # Driver function to calculate minimum    # time required    def solve(self, root, target):        info = Info()        self.calcTime(root, info, target)        return self.res  # Driver Codeif __name__ == '__main__':    # Construct tree shown in the above example    root = TreeNode(1)    root.left = TreeNode(2)    root.right = TreeNode(3)    root.left.left = TreeNode(4)    root.left.right = TreeNode(5)    root.right.left = TreeNode(6)    root.left.left.left = TreeNode(8)    root.left.right.left = TreeNode(9)    root.left.right.right = TreeNode(10)    root.left.right.left.left = TreeNode(11)     # Target Leaf Node    target = 11     # Print min time to burn the complete tree    s = Solution()    print(s.solve(root, target)) # This code is contributed by Naman Taneja
// C# program to find minimum time required// to burn the binary tree completelyusing System; class GFG{     // Tree Node    class Node    {        public int data;        public Node left, right;         public Node(int data)        {            this.data = data;            this.left = null;            this.right = null;        }    }     /*        ***********ADDITIONAL INFO*************        lDepth - maximum height of left subtree        rDepth - maximum height of right subtree        contains - stores true if tree rooted at current node                contains the first burnt node        time - time to reach fire from the initially burnt leaf            node to this node    */    class Data    {        public int leftDepth, rightDepth, time;        public bool contains;         public Data()        {            contains = false;            leftDepth = rightDepth = 0;            time = -1;        }    }     /*        Function to calculate time required to burn        tree completely                 node - address of current node        info - extra information about current node        target - node that is fired        res - stores the result    */    static void getResult(Node node, Data data,                            int target)    {         // Base case: if root is null        if (node == null)        {            return;        }         // If current node is leaf        if (node.left == null &&            node.right == null)        {             // If current node is the first burnt node            if (node.data == target)            {                data.contains = true;                data.time = 0;            }            return;        }         // Information about left child        Data leftData = new Data();        getResult(node.left, leftData, target);         // Information about right child        Data rightData = new Data();        getResult(node.right, rightData, target);         // If left subtree contains the fired node then        // time required to reach fire to current node        // will be (1 + time required for left child)        data.time = (leftData.contains) ?                    (leftData.time + 1) : -1;         // If right subtree contains the fired node then        // time required to reach fire to current node        // will be (1 + time required for right child)        if (data.time == -1)            data.time = (rightData.contains) ?                        (rightData.time + 1) : -1;         // Storing(true or false) if the tree rooted at        // current node contains the fired node        data.contains = (leftData.contains ||                        rightData.contains);         // Calculate the maximum depth of left subtree        data.leftDepth = (node.left == null) ?                        0 : (1 + Math.Max(                        leftData.leftDepth,                        leftData.rightDepth));         // Calculate the maximum depth of right subtree        data.rightDepth = (node.right == null) ?                        0 : (1 + Math.Max(                        rightData.leftDepth,                        rightData.rightDepth));         // Calculating answer        if (data.contains)        {             // If left subtree exists and            // it contains the fired node            if (leftData.contains)            {                 // calculate result                res = Math.Max(res, data.time +                                data.rightDepth);            }             // If right subtree exists and it            // contains the fired node            if (rightData.contains)            {                 // calculate result                res = Math.Max(res, data.time +                                data.leftDepth);            }        }    }     // To store the result    public static int res;     // Driver Code    public static void Main(String []args)    {         Node root = new Node(1);        root.left = new Node(2);        root.right = new Node(3);        root.left.left = new Node(4);        root.left.right = new Node(5);        root.right.left = new Node(6);        root.left.left.left = new Node(8);        root.left.right.left = new Node(9);        root.left.right.right = new Node(10);        root.left.right.left.left = new Node(11);         int target = 11;         res = 0;        getResult(root, new Data(), target);        Console.WriteLine(res);    }} // This code is contributed by PrinciRaj1992
6
 
princiraj1992
simmytarika5
namantaneja123
Amazon
Binary Tree
Flipkart
Grab
Tree
Flipkart
Amazon
Tree
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Introduction to Data Structures
Introduction to Tree Data Structure
Inorder Tree Traversal without Recursion
What is Data Structure: Types, Classifications and Applications
Binary Tree | Set 3 (Types of Binary Tree)
A program to check if a binary tree is BST or not
Lowest Common Ancestor in a Binary Tree | Set 1
Binary Tree | Set 2 (Properties)
Diameter of a Binary Tree