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++
#include <bits/stdc++.h>
using namespace std;
int max( int x, int y)
{
return (x > y) ? x : y;
}
class node
{
public :
int data;
node *left, *right;
};
int LISS(node *root)
{
if (root == NULL)
return 0;
int size_excl = LISS(root->left) +
LISS(root->right);
int size_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 max(size_incl, size_excl);
}
node* newNode( int data )
{
node* temp = new node();
temp->data = data;
temp->left = temp->right = NULL;
return temp;
}
int main()
{
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);
return 0;
}
|
C
#include <stdio.h>
#include <stdlib.h>
int max( int x, int y) { return (x > y)? x: y; }
struct node
{
int data;
struct node *left, *right;
};
int LISS( struct node *root)
{
if (root == NULL)
return 0;
int size_excl = LISS(root->left) + LISS(root->right);
int size_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 max(size_incl, size_excl);
}
struct node* newNode( int data )
{
struct node* temp = ( struct node *) malloc ( sizeof ( struct node) );
temp->data = data;
temp->left = temp->right = NULL;
return temp;
}
int main()
{
struct 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);
printf ( "Size of the Largest Independent Set is %d " , LISS(root));
return 0;
}
|
Java
import java.io.*;
class GFG {
static int max( int x, int y) { return (x > y) ? x : y; }
static class Node {
int data;
Node left, right;
};
static int LISS(Node root)
{
if (root == null )
return 0 ;
int size_excl = LISS(root.left) + LISS(root.right);
int 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 max(size_incl, size_excl);
}
static Node newNode( int data)
{
Node temp = new Node();
temp.data = data;
temp.left = temp.right = null ;
return temp;
}
public static void main(String args[])
{
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));
}
}
|
Python3
def max (x, y):
if (x > y):
return x
else :
return y
class node :
def __init__( self ):
self .data = 0
self .left = self .right = None
def LISS(root):
if (root = = None ) :
return 0
size_excl = LISS(root.left) + LISS(root.right)
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 max (size_incl, size_excl)
def newNode( data ) :
temp = node()
temp.data = data
temp.left = temp.right = None
return temp
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) )
|
C#
using System;
class LisTree
{
public class node
{
public int data, liss;
public node left, right;
public node( int data)
{
this .data = data;
this .liss = 0;
}
}
static int liss(node root)
{
if (root == null )
return 0;
if (root.liss != 0)
return root.liss;
if (root.left == null && root.right == null )
return root.liss = 1;
int liss_excl = liss(root.left) + liss(root.right);
int liss_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));
}
return root.liss = Math.Max(liss_excl, liss_incl);
}
public static void Main(String[] args)
{
node root = new node(20);
root.left = new node(8);
root.left.left = new node(4);
root.left.right = new node(12);
root.left.right.left = new node(10);
root.left.right.right = new node(14);
root.right = new node(22);
root.right.right = new node(25);
Console.WriteLine( "Size of the Largest Independent Set is " + liss(root));
}
}
|
Javascript
<script>
function max(x, y)
{
return (x > y) ? x : y;
}
class Node
{
constructor(data)
{
this .data = data;
this .left = this .right = null ;
}
}
function LISS(root)
{
if (root == null )
return 0;
let size_excl = LISS(root.left) +
LISS(root.right);
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 max(size_incl, size_excl);
}
let root = new Node(20);
root.left = new Node(8);
root.left.left = new Node(4);
root.left.right = new Node(12);
root.left.right.left = new Node(10);
root.left.right.right = new Node(14);
root.right = new Node(22);
root.right.right = new Node(25);
document.write( "Size of the Largest" +
" Independent Set is " +
LISS(root));
</script>
|
Output
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++
#include <bits/stdc++.h>
using namespace std;
int max( int x, int y) { return (x > y)? x: y; }
class node
{
public :
int data;
int liss;
node *left, *right;
};
int LISS(node *root)
{
if (root == NULL)
return 0;
if (root->liss)
return root->liss;
if (root->left == NULL && root->right == NULL)
return (root->liss = 1);
int liss_excl = LISS(root->left) + LISS(root->right);
int liss_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);
root->liss = max(liss_incl, liss_excl);
return root->liss;
}
node* newNode( int data)
{
node* temp = new node();
temp->data = data;
temp->left = temp->right = NULL;
temp->liss = 0;
return temp;
}
int main()
{
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);
return 0;
}
|
C
#include <stdio.h>
#include <stdlib.h>
int max( int x, int y) { return (x > y)? x: y; }
struct node
{
int data;
int liss;
struct node *left, *right;
};
int LISS( struct node *root)
{
if (root == NULL)
return 0;
if (root->liss)
return root->liss;
if (root->left == NULL && root->right == NULL)
return (root->liss = 1);
int liss_excl = LISS(root->left) + LISS(root->right);
int liss_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);
root->liss = max(liss_incl, liss_excl);
return root->liss;
}
struct node* newNode( int data)
{
struct node* temp = ( struct node *) malloc ( sizeof ( struct node) );
temp->data = data;
temp->left = temp->right = NULL;
temp->liss = 0;
return temp;
}
int main()
{
struct 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);
printf ( "Size of the Largest Independent Set is %d " , LISS(root));
return 0;
}
|
Java
import java.io.*;
public class LisTree
{
static class node
{
int data, liss;
node left, right;
public node( int data)
{
this .data = data;
this .liss = 0 ;
}
}
static int liss(node root)
{
if (root == null )
return 0 ;
if (root.liss != 0 )
return root.liss;
if (root.left == null && root.right == null )
return root.liss = 1 ;
int liss_excl = liss(root.left) + liss(root.right);
int liss_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));
}
return root.liss = Math.max(liss_excl, liss_incl);
}
public static void main(String[] args)
{
node root = new node( 20 );
root.left = new node( 8 );
root.left.left = new node( 4 );
root.left.right = new node( 12 );
root.left.right.left = new node( 10 );
root.left.right.right = new node( 14 );
root.right = new node( 22 );
root.right.right = new node( 25 );
System.out.println( "Size of the Largest Independent Set is " + liss(root));
}
}
|
Python3
class node:
def __init__( self , data):
self .data = data
self .left = self .right = None
self .liss = 0
def liss(root):
if root = = None :
return 0
if (root.liss):
return root.liss
if (root.left = = None and
root.right = = None ):
root.liss = 1
return root.liss
liss_excl = (liss(root.left) +
liss(root.right))
liss_incl = 1
if root.left ! = None :
liss_incl + = (liss(root.left.left) +
liss(root.left.right))
if root.right ! = None :
liss_incl + = (liss(root.right.left) +
liss(root.right.right))
root.liss = max (liss_excl, liss_incl)
return root.liss
root = 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))
|
C#
using System;
public class LisTree
{
public class node
{
public int data, liss;
public node left, right;
public node( int data)
{
this .data = data;
this .liss = 0;
}
}
static int liss(node root)
{
if (root == null )
return 0;
if (root.liss != 0)
return root.liss;
if (root.left == null && root.right == null )
return root.liss = 1;
int liss_excl = liss(root.left) + liss(root.right);
int liss_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));
}
return root.liss = Math.Max(liss_excl, liss_incl);
}
public static void Main(String[] args)
{
node root = new node(20);
root.left = new node(8);
root.left.left = new node(4);
root.left.right = new node(12);
root.left.right.left = new node(10);
root.left.right.right = new node(14);
root.right = new node(22);
root.right.right = new node(25);
Console.WriteLine( "Size of the Largest Independent Set is " + liss(root));
}
}
|
Javascript
<script>
class node {
constructor(data) {
this .data = data;
this .liss = 0;
this .left = null ;
this .right = null ;
}
}
function liss(root) {
if (root == null ) return 0;
if (root.liss != 0) return root.liss;
if (root.left == null && root.right == null )
return (root.liss = 1);
var liss_excl = liss(root.left) + liss(root.right);
var liss_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);
}
return (root.liss = Math.max(liss_excl, liss_incl));
}
var root = new node(20);
root.left = new node(8);
root.left.left = new node(4);
root.left.right = new node(12);
root.left.right.left = new node(10);
root.left.right.right = new node(14);
root.right = new node(22);
root.right.right = new node(25);
document.write(
"Size of the Largest Independent Set is " + liss(root)
);
</script>
|
Output
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.
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
08 Mar, 2023
Like Article
Save Article