Largest Independent Set Problem using Dynamic Programming
Last Updated :
23 Jul, 2025
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>
using namespace std;
// A utility function to find
// max of two integers
int max(int x, int y)
{
return (x > y) ? x : y;
}
/* A binary tree node has data,
pointer to left child and a
pointer to right child */
class node
{
public:
int data;
node *left, *right;
};
// The function returns size of the
// largest independent set in a given
// binary tree
int LISS(node *root)
{
if (root == NULL)
return 0;
// Calculate size excluding the current node
int size_excl = LISS(root->left) +
LISS(root->right);
// Calculate size including the current node
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 the maximum of two sizes
return max(size_incl, size_excl);
}
// A utility function to create a node
node* newNode( int data )
{
node* temp = new node();
temp->data = data;
temp->left = temp->right = NULL;
return temp;
}
// Driver Code
int main()
{
// 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);
return 0;
}
// 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 integers
int max(int x, int y) { return (x > y)? x: y; }
/* A binary tree node has data, pointer to left child and a pointer to
right child */
struct node
{
int data;
struct node *left, *right;
};
// The function returns size of the largest independent set in a given
// binary tree
int LISS(struct node *root)
{
if (root == NULL)
return 0;
// Calculate size excluding the current node
int size_excl = LISS(root->left) + LISS(root->right);
// Calculate size including the current node
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 the maximum of two sizes
return max(size_incl, size_excl);
}
// A utility function to create a node
struct node* newNode( int data )
{
struct node* temp = (struct node *) malloc( sizeof(struct node) );
temp->data = data;
temp->left = temp->right = NULL;
return temp;
}
// Driver program to test above functions
int main()
{
// Let us construct the tree given in the above diagram
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
// A naive recursive implementation of
// Largest Independent Set problem
import java.io.*;
class GFG {
// A utility function to find
// max of two integers
static int max(int x, int y) { return (x > y) ? x : y; }
/* A binary tree node has data,
pointer to left child and a
pointer to right child */
static class Node {
int data;
Node left, right;
};
// The function returns size of the
// largest independent set in a given
// binary tree
static int LISS(Node root)
{
if (root == null)
return 0;
// Calculate size excluding the current node
int size_excl = LISS(root.left) + LISS(root.right);
// Calculate size including the current node
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 the maximum of two sizes
return max(size_incl, size_excl);
}
// A utility function to create a node
static Node newNode(int data)
{
Node temp = new Node();
temp.data = data;
temp.left = temp.right = null;
return temp;
}
// Driver Code
public static void main(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
def max(x, y):
if(x > y):
return x
else:
return y
# A binary tree node has data,
#pointer to left child and a
#pointer to right child
class node :
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
def LISS(root):
if (root == None) :
return 0
# 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
return max(size_incl, size_excl)
# A utility function to create a node
def newNode( data ) :
temp = node()
temp.data = data
temp.left = temp.right = None
return temp
# 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
using System;
class LisTree
{
/* A binary tree node has data, pointer
to left child and a pointer to right
child */
public class node
{
public int data, liss;
public node left, right;
public node(int data)
{
this.data = data;
this.liss = 0;
}
}
// A memoization function returns size
// of the largest independent set in
// a given binary tree
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;
// Calculate size excluding the
// current node
int liss_excl = liss(root.left) + liss(root.right);
// Calculate size including the
// current node
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));
}
// Maximum of two sizes is LISS,
// store it for future uses.
return root.liss = Math.Max(liss_excl, liss_incl);
}
// Driver code
public static void Main(String[] args)
{
// Let us construct the tree given
// in the above diagram
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));
}
}
// 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 integers
function max(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 tree
function LISS(root)
{
if (root == null)
return 0;
// 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
return max(size_incl, size_excl);
}
// Driver Code
// Let us construct the tree
// given in the above diagram
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));
// This code is contributed by avanitrachhadiya2155
</script>
OutputSize 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>
using namespace std;
// A utility function to find max of two integers
int max(int x, int y) { return (x > y)? x: y; }
/* A binary tree node has data, pointer
to left child and a pointer to
right child */
class node
{
public:
int data;
int liss;
node *left, *right;
};
// A memoization function returns size
// of the largest independent set in
// a given binary tree
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);
// Calculate size excluding the current node
int liss_excl = LISS(root->left) + LISS(root->right);
// Calculate size including the current node
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);
// Maximum of two sizes is LISS, store it for future uses.
root->liss = max(liss_incl, liss_excl);
return root->liss;
}
// A utility function to create a node
node* newNode(int data)
{
node* temp = new node();
temp->data = data;
temp->left = temp->right = NULL;
temp->liss = 0;
return temp;
}
// Driver code
int main()
{
// 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);
return 0;
}
// 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 integers
int max(int x, int y) { return (x > y)? x: y; }
/* A binary tree node has data, pointer to left child and a pointer to
right child */
struct node
{
int data;
int liss;
struct node *left, *right;
};
// A memoization function returns size of the largest independent set in
// a given binary tree
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);
// Calculate size excluding the current node
int liss_excl = LISS(root->left) + LISS(root->right);
// Calculate size including the current node
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);
// Maximum of two sizes is LISS, store it for future uses.
root->liss = max(liss_incl, liss_excl);
return root->liss;
}
// A utility function to create a node
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;
}
// Driver program to test above functions
int main()
{
// Let us construct the tree given in the above diagram
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
// Java program for calculating LISS
// using dynamic programming
import java.io.*;
public class LisTree
{
/* A binary tree node has data, pointer
to left child and a pointer to right
child */
static class node
{
int data, liss;
node left, right;
public node(int data)
{
this.data = data;
this.liss = 0;
}
}
// A memoization function returns size
// of the largest independent set in
// a given binary tree
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;
// Calculate size excluding the
// current node
int liss_excl = liss(root.left) + liss(root.right);
// Calculate size including the
// current node
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));
}
// Maximum of two sizes is LISS,
// store it for future uses.
return root.liss = Math.max(liss_excl, liss_incl);
}
public static void main(String[] args)
{
// Let us construct the tree given
// in the above diagram
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));
}
}
// 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 child
class node:
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 tree
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
# Calculate size excluding the
# current node
liss_excl = (liss(root.left) +
liss(root.right))
# Calculate size including the
# current node
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))
# Maximum of two sizes is LISS,
# store it for future uses.
root.liss = max(liss_excl, liss_incl)
return root.liss
# Driver Code
# Let us construct the tree given
# in the above diagram
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))
# This code is contributed by nishthagoel712
C#
// C# program for calculating LISS
// using dynamic programming
using System;
public class LisTree
{
/* A binary tree node has data, pointer
to left child and a pointer to right
child */
public class node
{
public int data, liss;
public node left, right;
public node(int data)
{
this.data = data;
this.liss = 0;
}
}
// A memoization function returns size
// of the largest independent set in
// a given binary tree
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;
// Calculate size excluding the
// current node
int liss_excl = liss(root.left) + liss(root.right);
// Calculate size including the
// current node
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));
}
// Maximum of two sizes is LISS,
// store it for future uses.
return root.liss = Math.Max(liss_excl, liss_incl);
}
// Driver code
public static void Main(String[] args)
{
// Let us construct the tree given
// in the above diagram
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));
}
}
/* 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
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);
// Calculate size excluding the
// current node
var liss_excl = liss(root.left) + liss(root.right);
// Calculate size including the
// current node
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);
}
// 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
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>
OutputSize 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.
Similar Reads
Basics & Prerequisites
Data Structures
Array Data StructureIn this article, we introduce array, implementation in different popular languages, its basic operations and commonly seen problems / interview questions. An array stores items (in case of C/C++ and Java Primitive Arrays) or their references (in case of Python, JS, Java Non-Primitive) at contiguous
3 min read
String in Data StructureA string is a sequence of characters. The following facts make string an interesting data structure.Small set of elements. Unlike normal array, strings typically have smaller set of items. For example, lowercase English alphabet has only 26 characters. ASCII has only 256 characters.Strings are immut
2 min read
Hashing in Data StructureHashing is a technique used in data structures that efficiently stores and retrieves data in a way that allows for quick access. Hashing involves mapping data to a specific index in a hash table (an array of items) using a hash function. It enables fast retrieval of information based on its key. The
2 min read
Linked List Data StructureA linked list is a fundamental data structure in computer science. It mainly allows efficient insertion and deletion operations compared to arrays. Like arrays, it is also used to implement other data structures like stack, queue and deque. Hereâs the comparison of Linked List vs Arrays Linked List:
2 min read
Stack Data StructureA Stack is a linear data structure that follows a particular order in which the operations are performed. The order may be LIFO(Last In First Out) or FILO(First In Last Out). LIFO implies that the element that is inserted last, comes out first and FILO implies that the element that is inserted first
2 min read
Queue Data StructureA Queue Data Structure is a fundamental concept in computer science used for storing and managing data in a specific order. It follows the principle of "First in, First out" (FIFO), where the first element added to the queue is the first one to be removed. It is used as a buffer in computer systems
2 min read
Tree Data StructureTree Data Structure is a non-linear data structure in which a collection of elements known as nodes are connected to each other via edges such that there exists exactly one path between any two nodes. Types of TreeBinary Tree : Every node has at most two childrenTernary Tree : Every node has at most
4 min read
Graph Data StructureGraph Data Structure is a collection of nodes connected by edges. It's used to represent relationships between different entities. If you are looking for topic-wise list of problems on different topics like DFS, BFS, Topological Sort, Shortest Path, etc., please refer to Graph Algorithms. Basics of
3 min read
Trie Data StructureThe Trie data structure is a tree-like structure used for storing a dynamic set of strings. It allows for efficient retrieval and storage of keys, making it highly effective in handling large datasets. Trie supports operations such as insertion, search, deletion of keys, and prefix searches. In this
15+ min read
Algorithms
Searching AlgorithmsSearching algorithms are essential tools in computer science used to locate specific items within a collection of data. In this tutorial, we are mainly going to focus upon searching in an array. When we search an item in an array, there are two most common algorithms used based on the type of input
2 min read
Sorting AlgorithmsA Sorting Algorithm is used to rearrange a given array or list of elements in an order. For example, a given array [10, 20, 5, 2] becomes [2, 5, 10, 20] after sorting in increasing order and becomes [20, 10, 5, 2] after sorting in decreasing order. There exist different sorting algorithms for differ
3 min read
Introduction to RecursionThe process in which a function calls itself directly or indirectly is called recursion and the corresponding function is called a recursive function. A recursive algorithm takes one step toward solution and then recursively call itself to further move. The algorithm stops once we reach the solution
14 min read
Greedy AlgorithmsGreedy algorithms are a class of algorithms that make locally optimal choices at each step with the hope of finding a global optimum solution. At every step of the algorithm, we make a choice that looks the best at the moment. To make the choice, we sometimes sort the array so that we can always get
3 min read
Graph AlgorithmsGraph is a non-linear data structure like tree data structure. The limitation of tree is, it can only represent hierarchical data. For situations where nodes or vertices are randomly connected with each other other, we use Graph. Example situations where we use graph data structure are, a social net
3 min read
Dynamic Programming or DPDynamic Programming is an algorithmic technique with the following properties.It is mainly an optimization over plain recursion. Wherever we see a recursive solution that has repeated calls for the same inputs, we can optimize it using Dynamic Programming. The idea is to simply store the results of
3 min read
Bitwise AlgorithmsBitwise algorithms in Data Structures and Algorithms (DSA) involve manipulating individual bits of binary representations of numbers to perform operations efficiently. These algorithms utilize bitwise operators like AND, OR, XOR, NOT, Left Shift, and Right Shift.BasicsIntroduction to Bitwise Algorit
4 min read
Advanced
Segment TreeSegment Tree is a data structure that allows efficient querying and updating of intervals or segments of an array. It is particularly useful for problems involving range queries, such as finding the sum, minimum, maximum, or any other operation over a specific range of elements in an array. The tree
3 min read
Pattern SearchingPattern searching algorithms are essential tools in computer science and data processing. These algorithms are designed to efficiently find a particular pattern within a larger set of data. Patten SearchingImportant Pattern Searching Algorithms:Naive String Matching : A Simple Algorithm that works i
2 min read
GeometryGeometry is a branch of mathematics that studies the properties, measurements, and relationships of points, lines, angles, surfaces, and solids. From basic lines and angles to complex structures, it helps us understand the world around us.Geometry for Students and BeginnersThis section covers key br
2 min read
Interview Preparation
Practice Problem