Given a Binary Tree, find size of the Largest Independent Set(LIS) in it. A subset of all tree nodes is an independent set if there is no edge between any two nodes of the subset.
For example, consider the following binary tree. The largest independent set(LIS) is {10, 40, 60, 70, 80} and size of the LIS is 5.
A Dynamic Programming solution solves a given problem using solutions of subproblems in bottom up manner. Can the given problem be solved using solutions to subproblems? If yes, then what are the subproblems? Can we find largest independent set size (LISS) for a node X if we know LISS for all descendants of X? If a node is considered as part of LIS, then its children cannot be part of LIS, but its grandchildren can be. Following is optimal substructure property.
1) Optimal Substructure: 
Let LISS(X) indicates size of largest independent set of a tree with root X. 
     LISS(X) = MAX { (1 + sum of LISS for all grandchildren of X),
                     (sum of LISS for all children of X) }
The idea is simple, there are two possibilities for every node X, either X is a member of the set or not a member. If X is a member, then the value of LISS(X) is 1 plus LISS of all grandchildren. If X is not a member, then the value is sum of LISS of all children.
2) Overlapping Subproblems 
Following is recursive implementation that simply follows the recursive structure mentioned above. 
C++
| // A naive recursive implementation of// Largest Independent Set problem #include <bits/stdc++.h>usingnamespacestd; // A utility function to find // max of two integers intmax(intx, inty) {     return(x > y) ? x : y; } /* A binary tree node has data, pointer to left child and a pointer to right child */classnode {     public:    intdata;     node *left, *right; }; // The function returns size of the // largest independent set in a given // binary tree intLISS(node *root) {     if(root == NULL)     return0;     // Calculate size excluding the current node     intsize_excl = LISS(root->left) +                     LISS(root->right);     // Calculate size including the current node     intsize_incl = 1;     if(root->left)         size_incl += LISS(root->left->left) +                     LISS(root->left->right);     if(root->right)         size_incl += LISS(root->right->left) +                      LISS(root->right->right);     // Return the maximum of two sizes     returnmax(size_incl, size_excl); } // A utility function to create a node node* newNode( intdata ) {     node* temp = newnode();    temp->data = data;     temp->left = temp->right = NULL;     returntemp; } // Driver Codeintmain() {     // Let us construct the tree     // given in the above diagram     node *root = newNode(20);     root->left = newNode(8);     root->left->left = newNode(4);     root->left->right = newNode(12);     root->left->right->left = newNode(10);     root->left->right->right = newNode(14);     root->right = newNode(22);     root->right->right = newNode(25);     cout << "Size of the Largest"         << " Independent Set is "         << LISS(root);     return0; } // This is code is contributed // by rathbhupendra | 
C
| // A naive recursive implementation of Largest Independent Set problem#include <stdio.h>#include <stdlib.h>// A utility function to find max of two integersintmax(intx, inty) { return(x > y)? x: y; }/* A binary tree node has data, pointer to left child and a pointer to    right child */structnode{    intdata;    structnode *left, *right;};// The function returns size of the largest independent set in a given // binary treeintLISS(structnode *root){    if(root == NULL)       return0;    // Calculate size excluding the current node    intsize_excl = LISS(root->left) + LISS(root->right);    // Calculate size including the current node    intsize_incl = 1;    if(root->left)       size_incl += LISS(root->left->left) + LISS(root->left->right);    if(root->right)       size_incl += LISS(root->right->left) + LISS(root->right->right);    // Return the maximum of two sizes    returnmax(size_incl, size_excl);}// A utility function to create a nodestructnode* newNode( intdata ){    structnode* temp = (structnode *) malloc( sizeof(structnode) );    temp->data = data;    temp->left = temp->right = NULL;    returntemp;}// Driver program to test above functionsintmain(){    // Let us construct the tree given in the above diagram    structnode *root         = newNode(20);    root->left                = newNode(8);    root->left->left          = newNode(4);    root->left->right         = newNode(12);    root->left->right->left   = newNode(10);    root->left->right->right  = newNode(14);    root->right               = newNode(22);    root->right->right        = newNode(25);    printf("Size of the Largest Independent Set is %d ", LISS(root));    return0;} | 
Java
| // A naive recursive implementation of// Largest Independent Set problemimportjava.io.*;classGFG {    // A utility function to find    // max of two integers    staticintmax(intx, inty) { return(x > y) ? x : y; }    /* A binary tree node has data,    pointer to left child and a    pointer to right child */    staticclassNode {        intdata;        Node left, right;    };    // The function returns size of the    // largest independent set in a given    // binary tree    staticintLISS(Node root)    {        if(root == null)            return0;        // Calculate size excluding the current node        intsize_excl = LISS(root.left) + LISS(root.right);        // Calculate size including the current node        intsize_incl = 1;        if(root.left != null)            size_incl += LISS(root.left.left)                         + LISS(root.left.right);        if(root.right != null)            size_incl += LISS(root.right.left)                         + LISS(root.right.right);        // Return the maximum of two sizes        returnmax(size_incl, size_excl);    }    // A utility function to create a node    staticNode newNode(intdata)    {        Node temp = newNode();        temp.data = data;        temp.left = temp.right = null;        returntemp;    }    // Driver Code    publicstaticvoidmain(String args[])    {        // Let us construct the tree        // given in the above diagram        Node root = newNode(20);        root.left = newNode(8);        root.left.left = newNode(4);        root.left.right = newNode(12);        root.left.right.left = newNode(10);        root.left.right.right = newNode(14);        root.right = newNode(22);        root.right.right = newNode(25);        System.out.println("Size of the Largest"                           + " Independent Set is "                           + LISS(root));    }}// This code has been contributed by 29AjayKumar | 
Python3
| # A naive recursive implementation of# Largest Independent Set problem # A utility function to find # max of two integers defmax(x, y):     if(x > y):        returnx    else:        returny# A binary tree node has data, #pointer to left child and a #pointer to right childclassnode :    def__init__(self):        self.data =0        self.left =self.right =None# The function returns size of the # largest independent set in a given # binary tree defLISS(root):     if(root ==None) :        return0    # Calculate size excluding the current node     size_excl =LISS(root.left) +LISS(root.right)     # Calculate size including the current node     size_incl =1    if(root.left !=None):         size_incl +=LISS(root.left.left) +\                    LISS(root.left.right)     if(root.right !=None):         size_incl +=LISS(root.right.left) +\                    LISS(root.right.right)     # Return the maximum of two sizes     returnmax(size_incl, size_excl) # A utility function to create a node defnewNode( data ) :    temp =node()    temp.data =data     temp.left =temp.right =None    returntemp # Driver Code# Let us construct the tree # given in the above diagram root =newNode(20) root.left =newNode(8) root.left.left =newNode(4) root.left.right =newNode(12) root.left.right.left =newNode(10) root.left.right.right =newNode(14) root.right =newNode(22) root.right.right =newNode(25) print( "Size of the Largest"        , " Independent Set is "        , LISS(root) )# This code is contributed by Arnab Kundu | 
C#
| // C# program for calculating LISS // using dynamic programming usingSystem;classLisTree {     /* A binary tree node has data, pointer     to left child and a pointer to right     child */    publicclassnode     {         publicintdata, liss;         publicnode left, right;         publicnode(intdata)         {             this.data = data;             this.liss = 0;         }     }     // A memoization function returns size     // of the largest independent set in     // a given binary tree     staticintliss(node root)     {         if(root == null)             return0;         if(root.liss != 0)             returnroot.liss;         if(root.left == null&& root.right == null)             returnroot.liss = 1;                 // Calculate size excluding the         // current node         intliss_excl = liss(root.left) + liss(root.right);                 // Calculate size including the         // current node         intliss_incl = 1;         if(root.left != null)         {             liss_incl += (liss(root.left.left) +                         liss(root.left.right));         }         if(root.right != null)         {             liss_incl += (liss(root.right.left) +                         liss(root.right.right));         }                 // Maximum of two sizes is LISS,         // store it for future uses.         returnroot.liss = Math.Max(liss_excl, liss_incl);     }     // Driver code    publicstaticvoidMain(String[] args)     {         // Let us construct the tree given         // in the above diagram                 node root = newnode(20);         root.left = newnode(8);         root.left.left = newnode(4);         root.left.right = newnode(12);         root.left.right.left = newnode(10);         root.left.right.right = newnode(14);         root.right = newnode(22);         root.right.right = newnode(25);         Console.WriteLine("Size of the Largest Independent Set is "+ liss(root));     } } // This code is contributed by Princi Singh | 
Javascript
| <script>// A naive recursive implementation of// Largest Independent Set problem// A utility function to find// max of two integersfunctionmax(x, y){    return(x > y) ? x : y;}// A binary tree node has data,// pointer to left child and a// pointer to right child class Node{    constructor(data)    {        this.data = data;        this.left = this.right = null;    }}// The function returns size of the// largest independent set in a given// binary treefunctionLISS(root){    if(root == null)    return0;     // Calculate size excluding the current node    let size_excl = LISS(root.left) +                    LISS(root.right);     // Calculate size including the current node    let size_incl = 1;    if(root.left != null)        size_incl += LISS(root.left.left) +                     LISS(root.left.right);    if(root.right != null)        size_incl += LISS(root.right.left) +                     LISS(root.right.right);     // Return the maximum of two sizes    returnmax(size_incl, size_excl);}// Driver Code// Let us construct the tree// given in the above diagramlet root = newNode(20);root.left = newNode(8);root.left.left = newNode(4);root.left.right = newNode(12);root.left.right.left = newNode(10);root.left.right.right = newNode(14);root.right = newNode(22);root.right.right = newNode(25);document.write("Size of the Largest"+                " Independent Set is "+                LISS(root));// This code is contributed by avanitrachhadiya2155</script> | 
Size of the Largest Independent Set is 5
Time Complexity of the above naive recursive approach is exponential. It should be noted that the above function computes the same subproblems again and again. For example, LISS of node with value 50 is evaluated for node with values 10 and 20 as 50 is grandchild of 10 and child of 20.
Auxiliary Space: O(n) ,here n is the number of nodes in given Binary tree.
Since same subproblems are called again, this problem has Overlapping Subproblems property. So LISS problem has both properties (see this and this) of a dynamic programming problem. Like other typical Dynamic Programming(DP) problems, recomputations of same subproblems can be avoided by storing the solutions to subproblems and solving problems in bottom up manner.
Following are implementation of Dynamic Programming based solution. In the following solution, an additional field ‘liss’ is added to tree nodes. The initial value of ‘liss’ is set as 0 for all nodes. The recursive function LISS() calculates ‘liss’ for a node only if it is not already set.
C++
| /* Dynamic programming based program for Largest Independent Set problem */#include <bits/stdc++.h>usingnamespacestd; // A utility function to find max of two integers intmax(intx, inty) { return(x > y)? x: y; } /* A binary tree node has data, pointerto left child and a pointer to right child */classnode {     public:    intdata;     intliss;     node *left, *right; }; // A memoization function returns size // of the largest independent set in // a given binary tree intLISS(node *root) {     if(root == NULL)         return0;     if(root->liss)         returnroot->liss;     if(root->left == NULL && root->right == NULL)         return(root->liss = 1);     // Calculate size excluding the current node     intliss_excl = LISS(root->left) + LISS(root->right);     // Calculate size including the current node     intliss_incl = 1;     if(root->left)         liss_incl += LISS(root->left->left) + LISS(root->left->right);     if(root->right)         liss_incl += LISS(root->right->left) + LISS(root->right->right);     // Maximum of two sizes is LISS, store it for future uses.     root->liss = max(liss_incl, liss_excl);     returnroot->liss; } // A utility function to create a node node* newNode(intdata) {     node* temp = newnode();     temp->data = data;     temp->left = temp->right = NULL;     temp->liss = 0;     returntemp; } // Driver codeintmain() {     // Let us construct the tree     // given in the above diagram     node *root     = newNode(20);     root->left         = newNode(8);     root->left->left     = newNode(4);     root->left->right     = newNode(12);     root->left->right->left = newNode(10);     root->left->right->right = newNode(14);     root->right         = newNode(22);     root->right->right     = newNode(25);     cout << "Size of the Largest Independent Set is "<< LISS(root);     return0; } // This code is contributed by rathbhupendra | 
C
| /* Dynamic programming based program for Largest Independent Set problem */#include <stdio.h>#include <stdlib.h>// A utility function to find max of two integersintmax(intx, inty) { return(x > y)? x: y; }/* A binary tree node has data, pointer to left child and a pointer to    right child */structnode{    intdata;    intliss;    structnode *left, *right;};// A memoization function returns size of the largest independent set in//  a given binary treeintLISS(structnode *root){    if(root == NULL)        return0;    if(root->liss)        returnroot->liss;    if(root->left == NULL && root->right == NULL)        return(root->liss = 1);    // Calculate size excluding the current node    intliss_excl = LISS(root->left) + LISS(root->right);    // Calculate size including the current node    intliss_incl = 1;    if(root->left)        liss_incl += LISS(root->left->left) + LISS(root->left->right);    if(root->right)        liss_incl += LISS(root->right->left) + LISS(root->right->right);    // Maximum of two sizes is LISS, store it for future uses.    root->liss = max(liss_incl, liss_excl);    returnroot->liss;}// A utility function to create a nodestructnode* newNode(intdata){    structnode* temp = (structnode *) malloc( sizeof(structnode) );    temp->data = data;    temp->left = temp->right = NULL;    temp->liss = 0;    returntemp;}// Driver program to test above functionsintmain(){    // Let us construct the tree given in the above diagram    structnode *root         = newNode(20);    root->left                = newNode(8);    root->left->left          = newNode(4);    root->left->right         = newNode(12);    root->left->right->left   = newNode(10);    root->left->right->right  = newNode(14);    root->right               = newNode(22);    root->right->right        = newNode(25);    printf("Size of the Largest Independent Set is %d ", LISS(root));    return0;} | 
Java
| // Java program for calculating LISS // using dynamic programmingimportjava.io.*;publicclassLisTree {    /* A binary tree node has data, pointer        to left child and a pointer to right       child */    staticclassnode     {        intdata, liss;        node left, right;        publicnode(intdata)         {            this.data = data;            this.liss = 0;        }    }    // A memoization function returns size     // of the largest independent set in    // a given binary tree    staticintliss(node root)     {        if(root == null)            return0;        if(root.liss != 0)            returnroot.liss;        if(root.left == null&& root.right == null)            returnroot.liss = 1;                // Calculate size excluding the         // current node        intliss_excl = liss(root.left) + liss(root.right);                // Calculate size including the         // current node        intliss_incl = 1;        if(root.left != null)         {            liss_incl += (liss(root.left.left) + liss(root.left.right));        }        if(root.right != null)         {            liss_incl += (liss(root.right.left) + liss(root.right.right));        }                // Maximum of two sizes is LISS,         // store it for future uses.        returnroot.liss = Math.max(liss_excl, liss_incl);    }    publicstaticvoidmain(String[] args)     {        // Let us construct the tree given         // in the above diagram                node root = newnode(20);        root.left = newnode(8);        root.left.left = newnode(4);        root.left.right = newnode(12);        root.left.right.left = newnode(10);        root.left.right.right = newnode(14);        root.right = newnode(22);        root.right.right = newnode(25);        System.out.println("Size of the Largest Independent Set is "+ liss(root));    }}// This code is contributed by Rishabh Mahrsee | 
Python3
| # Python3 program for calculating LISS# using dynamic programming# A binary tree node has data,# pointer to left child and a# pointer to right childclassnode:    def__init__(self, data):                self.data =data        self.left =self.right =None        self.liss =0# A memoization function returns size# of the largest independent set in# a given binary treedefliss(root):        ifroot ==None:        return0          if(root.liss):        returnroot.liss        if(root.left ==Noneand        root.right ==None):        root.liss =1        returnroot.liss    # Calculate size excluding the    # current node    liss_excl =(liss(root.left) +                 liss(root.right))    # Calculate size including the    # current node    liss_incl =1    ifroot.left !=None:        liss_incl +=(liss(root.left.left) +                      liss(root.left.right))            ifroot.right !=None:        liss_incl +=(liss(root.right.left) +                      liss(root.right.right))            # Maximum of two sizes is LISS,    # store it for future uses.    root.liss =max(liss_excl, liss_incl)        returnroot.liss    # Driver Code# Let us construct the tree given# in the above diagramroot =node(20)root.left =node(8)root.left.left =node(4)root.left.right =node(12)root.left.right.left =node(10)root.left.right.right =node(14)root.right =node(22)root.right.right =node(25)print("Size of the Largest Independent "\      "Set is ", liss(root))# This code is contributed by nishthagoel712 | 
C#
| // C# program for calculating LISS // using dynamic programmingusingSystem;    publicclassLisTree {    /* A binary tree node has data, pointer     to left child and a pointer to right    child */    publicclassnode     {        publicintdata, liss;        publicnode left, right;        publicnode(intdata)         {            this.data = data;            this.liss = 0;        }    }    // A memoization function returns size     // of the largest independent set in    // a given binary tree    staticintliss(node root)     {        if(root == null)            return0;        if(root.liss != 0)            returnroot.liss;        if(root.left == null&& root.right == null)            returnroot.liss = 1;                // Calculate size excluding the         // current node        intliss_excl = liss(root.left) + liss(root.right);                // Calculate size including the         // current node        intliss_incl = 1;        if(root.left != null)         {            liss_incl += (liss(root.left.left) + liss(root.left.right));        }        if(root.right != null)         {            liss_incl += (liss(root.right.left) + liss(root.right.right));        }                // Maximum of two sizes is LISS,         // store it for future uses.        returnroot.liss = Math.Max(liss_excl, liss_incl);    }    // Driver code    publicstaticvoidMain(String[] args)     {        // Let us construct the tree given         // in the above diagram                node root = newnode(20);        root.left = newnode(8);        root.left.left = newnode(4);        root.left.right = newnode(12);        root.left.right.left = newnode(10);        root.left.right.right = newnode(14);        root.right = newnode(22);        root.right.right = newnode(25);        Console.WriteLine("Size of the Largest Independent Set is "+ liss(root));    }}/* This code is contributed by PrinciRaj1992 */ | 
Javascript
| <script>      // JavaScript program for calculating LISS      // using dynamic programming      /* A binary tree node has data, pointer         to left child and a pointer to right        child */      class node {        constructor(data) {          this.data = data;          this.liss = 0;          this.left = null;          this.right = null;        }      }      // A memoization function returns size      // of the largest independent set in      // a given binary tree      functionliss(root) {        if(root == null) return0;        if(root.liss != 0) returnroot.liss;        if(root.left == null&& root.right == null)         return(root.liss = 1);        // Calculate size excluding the        // current node        varliss_excl = liss(root.left) + liss(root.right);        // Calculate size including the        // current node        varliss_incl = 1;        if(root.left != null) {          liss_incl += liss(root.left.left) + liss(root.left.right);        }        if(root.right != null) {          liss_incl += liss(root.right.left) + liss(root.right.right);        }        // Maximum of two sizes is LISS,        // store it for future uses.        return(root.liss = Math.max(liss_excl, liss_incl));      }      // Driver code      // Let us construct the tree given      // in the above diagram      varroot = newnode(20);      root.left = newnode(8);      root.left.left = newnode(4);      root.left.right = newnode(12);      root.left.right.left = newnode(10);      root.left.right.right = newnode(14);      root.right = newnode(22);      root.right.right = newnode(25);      document.write(      "Size of the Largest Independent Set is "+ liss(root)      );      </script> | 
Size of the Largest Independent Set is 5
Time Complexity: O(n) where n is the number of nodes in given Binary tree.
Auxiliary Space: O(n)
Following extensions to above solution can be tried as an exercise. 
1) Extend the above solution for n-ary tree. 
2) The above solution modifies the given tree structure by adding an additional field ‘liss’ to tree nodes. Extend the solution so that it doesn’t modify the tree structure.
3) The above solution only returns size of LIS, it doesn’t print elements of LIS. Extend the solution to print all nodes that are part of LIS.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
 
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!


 
                                    








