# Dynamic Programming | Set 3 (Longest Increasing Subsequence)

We have discussed Overlapping Subproblems and Optimal Substructure properties in Set 1 and Set 2 respectively.

Let us discuss Longest Increasing Subsequence (LIS) problem as an example problem that can be solved using Dynamic Programming.
The longest Increasing Subsequence (LIS) problem is to find the length of the longest subsequence of a given sequence such that all elements of the subsequence are sorted in increasing order. For example, length of LIS for { 10, 22, 9, 33, 21, 50, 41, 60, 80 } is 6 and LIS is {10, 22, 33, 50, 60, 80}.

## We strongly recommend that you click here and practice it, before moving on to the solution.

Optimal Substructure:
Let arr[0..n-1] be the input array and L(i) be the length of the LIS till index i such that arr[i] is part of LIS and arr[i] is the last element in LIS, then L(i) can be recursively written as.
L(i) = { 1 + Max ( L(j) ) } where j < i and arr[j] < arr[i] and if there is no such j then L(i) = 1
To get LIS of a given array, we need to return max(L(i)) where 0 < i < n So the LIS problem has optimal substructure property as the main problem can be solved using solutions to subproblems.

Overlapping Subproblems:
Following is simple recursive implementation of the LIS problem. The implementation simply follows the recursive structure mentioned above. The value of lis ending with every element is returned using max_ending_here. The overall lis is returned using pointer to a variable max.

## C/C++

```/* A Naive C/C++ recursive implementation of LIS problem */
#include<stdio.h>
#include<stdlib.h>

/* To make use of recursive calls, this function must return
two things:
1) Length of LIS ending with element arr[n-1]. We use
max_ending_here for this purpose
2) Overall maximum as the LIS may end with an element
before arr[n-1] max_ref is used this purpose.
The value of LIS of full array of size n is stored in
*max_ref which is our final result */
int _lis( int arr[], int n, int *max_ref)
{
/* Base case */
if (n == 1)
return 1;

// 'max_ending_here' is length of LIS ending with arr[n-1]
int res, max_ending_here = 1;

/* Recursively get all LIS ending with arr[0], arr[1] ...
arr[n-2]. If   arr[i-1] is smaller than arr[n-1], and
max ending with arr[n-1] needs to be updated, then
update it */
for (int i = 1; i < n; i++)
{
res = _lis(arr, i, max_ref);
if (arr[i-1] < arr[n-1] && res + 1 > max_ending_here)
max_ending_here = res + 1;
}

// Compare max_ending_here with the overall max. And
// update the overall max if needed
if (*max_ref < max_ending_here)
*max_ref = max_ending_here;

// Return length of LIS ending with arr[n-1]
return max_ending_here;
}

// The wrapper function for _lis()
int lis(int arr[], int n)
{
// The max variable holds the result
int max = 1;

// The function _lis() stores its result in max
_lis( arr, n, &max );

// returns max
return max;
}

/* Driver program to test above function */
int main()
{
int arr[] = { 10, 22, 9, 33, 21, 50, 41, 60 };
int n = sizeof(arr)/sizeof(arr[0]);
printf("Length of lis is %d\n",
lis( arr, n ));
return 0;
}
```

## Java

```/* A Naive Java Program for LIS Implementation */
class LIS
{
static int max_ref; // stores the LIS

/* To make use of recursive calls, this function must return
two things:
1) Length of LIS ending with element arr[n-1]. We use
max_ending_here for this purpose
2) Overall maximum as the LIS may end with an element
before arr[n-1] max_ref is used this purpose.
The value of LIS of full array of size n is stored in
*max_ref which is our final result */
static int _lis(int arr[], int n)
{
// base case
if (n == 1)
return 1;

// 'max_ending_here' is length of LIS ending with arr[n-1]
int res, max_ending_here = 1;

/* Recursively get all LIS ending with arr[0], arr[1] ...
arr[n-2]. If   arr[i-1] is smaller than arr[n-1], and
max ending with arr[n-1] needs to be updated, then
update it */
for (int i = 1; i < n; i++)
{
res = _lis(arr, i);
if (arr[i-1] < arr[n-1] && res + 1 > max_ending_here)
max_ending_here = res + 1;
}

// Compare max_ending_here with the overall max. And
// update the overall max if needed
if (max_ref < max_ending_here)
max_ref = max_ending_here;

// Return length of LIS ending with arr[n-1]
return max_ending_here;
}

// The wrapper function for _lis()
static int lis(int arr[], int n)
{
// The max variable holds the result
max_ref = 1;

// The function _lis() stores its result in max
_lis( arr, n);

// returns max
return max_ref;
}

// driver program to test above functions
public static void main(String args[])
{
int arr[] = { 10, 22, 9, 33, 21, 50, 41, 60 };
int n = arr.length;
System.out.println("Length of lis is "
+ lis(arr, n) + "\n");
}
}
/*This code is contributed by Rajat Mishra*/
```

## Python

```# A naive Python implementation of LIS problem

""" To make use of recursive calls, this function must return
two things:
1) Length of LIS ending with element arr[n-1]. We use
max_ending_here for this purpose
2) Overall maximum as the LIS may end with an element
before arr[n-1] max_ref is used this purpose.
The value of LIS of full array of size n is stored in
*max_ref which is our final result """

# global variable to store the maximum
global maximum

def _lis(arr , n ):

# to allow the access of global variable
global maximum

# Base Case
if n == 1 :
return 1

# maxEndingHere is the length of LIS ending with arr[n-1]
maxEndingHere = 1

"""Recursively get all LIS ending with arr[0], arr[1]..arr[n-2]
IF arr[n-1] is maller than arr[n-1], and max ending with
arr[n-1] needs to be updated, then update it"""
for i in xrange(1, n):
res = _lis(arr , i)
if arr[i-1] < arr[n-1] and res+1 > maxEndingHere:
maxEndingHere = res +1

# Compare maxEndingHere with overall maximum. And
# update the overall maximum if needed
maximum = max(maximum , maxEndingHere)

return maxEndingHere

def lis(arr):

# to allow the access of global variable
global maximum

# lenght of arr
n = len(arr)

# maximum variable holds the result
maximum = 1

# The function _lis() stores its result in maximum
_lis(arr , n)

return maximum

# Driver program to test the above function
arr = [10 , 22 , 9 , 33 , 21 , 50 , 41 , 60]
n = len(arr)
print "Length of lis is ", lis(arr)

# This code is contributed by NIKHIL KUMAR SINGH
```
`Length of lis is 5`

Considering the above implementation, following is recursion tree for an array of size 4. lis(n) gives us the length of LIS for arr[].

```              lis(4)
/        |     \
lis(3)    lis(2)   lis(1)
/   \        /
lis(2) lis(1) lis(1)
/
lis(1)
```

We can see that there are many subproblems which are solved again and again. So this problem has Overlapping Substructure property and recomputation of same subproblems can be avoided by either using Memoization or Tabulation. Following is a tabluated implementation for the LIS problem.

## C/C++

```/* Dynamic Programming C/C++ implementation of LIS problem */
#include<stdio.h>
#include<stdlib.h>

/* lis() returns the length of the longest increasing
subsequence in arr[] of size n */
int lis( int arr[], int n )
{
int *lis, i, j, max = 0;
lis = (int*) malloc ( sizeof( int ) * n );

/* Initialize LIS values for all indexes */
for (i = 0; i < n; i++ )
lis[i] = 1;

/* Compute optimized LIS values in bottom up manner */
for (i = 1; i < n; i++ )
for (j = 0; j < i; j++ )
if ( arr[i] > arr[j] && lis[i] < lis[j] + 1)
lis[i] = lis[j] + 1;

/* Pick maximum of all LIS values */
for (i = 0; i < n; i++ )
if (max < lis[i])
max = lis[i];

/* Free memory to avoid memory leak */
free(lis);

return max;
}

/* Driver program to test above function */
int main()
{
int arr[] = { 10, 22, 9, 33, 21, 50, 41, 60 };
int n = sizeof(arr)/sizeof(arr[0]);
printf("Length of lis is %d\n", lis( arr, n ) );
return 0;
}
```

## Java

```/* Dynamic Programming Java implementation of LIS problem */

class LIS
{
/* lis() returns the length of the longest increasing
subsequence in arr[] of size n */
static int lis(int arr[],int n)
{
int lis[] = new int[n];
int i,j,max = 0;

/* Initialize LIS values for all indexes */
for ( i = 0; i < n; i++ )
lis[i] = 1;

/* Compute optimized LIS values in bottom up manner */
for ( i = 1; i < n; i++ )
for ( j = 0; j < i; j++ )
if ( arr[i] > arr[j] && lis[i] < lis[j] + 1)
lis[i] = lis[j] + 1;

/* Pick maximum of all LIS values */
for ( i = 0; i < n; i++ )
if ( max < lis[i] )
max = lis[i];

return max;
}

public static void main(String args[])
{
int arr[] = { 10, 22, 9, 33, 21, 50, 41, 60 };
int n = arr.length;
System.out.println("Length of lis is " + lis( arr, n ) + "\n" );
}
}
/*This code is contributed by Rajat Mishra*/
```

## Python

```# Dynamic programming Python implementation of LIS problem

# lis returns length of the longest increasing subsequence
# in arr of size n
def lis(arr):
n = len(arr)

# Declare the list (array) for LIS and initialize LIS
# values for all indexes
lis = [1]*n

# Compute optimized LIS values in bottom up manner
for i in range (1 , n):
for j in range(0 , i):
if arr[i] > arr[j] and lis[i]< lis[j] + 1 :
lis[i] = lis[j]+1

# Initialize maximum to 0 to get the maximum of all
# LIS
maximum = 0

# Pick maximum of all LIS values
for i in range(n):
maximum = max(maximum , lis[i])

return maximum
# end of lis function

# Driver program to test above function
arr = [10, 22, 9, 33, 21, 50, 41, 60]
print "Length of lis is", lis(arr)
# This code is contributed by Nikhil Kumar Singh
```

Output:

`Length of lis is 5`

Note that the time complexity of the above Dynamic Programming (DP) solution is O(n^2) and there is a O(nLogn) solution for the LIS problem. We have not discussed the O(n Log n) solution here as the purpose of this post is to explain Dynamic Programming with a simple example. See below post for O(n Log n) solution.

Longest Increasing Subsequence Size (N log N)

# Company Wise Coding Practice    Topic Wise Coding Practice

• konig_-

In the description, for this array of numbers :
{ 10, 22, 9, 33, 21, 50, 41, 60, 80 }

the following is given as anwer:
length of LIS is 6
and
LIS is {10, 22, 33, 50, 60, 80}.

will {10, 22, 33, 41, 60, 80} also be considered as an LIS?

• Mukesh M

Generating a BST with given Array will give LIS being longest branch in O(nLogn). Correct me if I am wrong here.

• Manikanta karanam

Interesting thought, but I guess it will not work if you consider any longest branch.

It is only right if you consider the longest right-only branch. Otherwise its not the longest increasing sub-sequence.

• Mukesh M

Thanks for correcting me. Yes checking for right-only branch from any node will do and still that is O(nLogn) solution.

• Manikanta karanam

Won’t work actually, since BST doesn’t guarantee insertion order…

For example:
Input:
0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15

Largest subsequence:
0, 2, 6, 9, 13, 15

But we get a sequence of length 5 with BST.

• Mukesh M

yups now I see my mistake.

• ravneet

Here a version which also prints the longest LIS
http://ideone.com/1f2E9I

• Sandeep

I have found a O(n) time solution of the above problem using dynamic programming in Java. I am sharing the solution below.

/*Begin*/
public int[] getLCS(int[] arr){

int arrLength = arr.length;
int[] dp = new int[arrLength];
int count = 0;

if(arrLength == 0){
return dp;
}

dp[0] = arr[0]; count = 1;

for(int i = 1; i dp[count-1])
{
dp[count] = arr[i];
count++;
}
}
return dp;
}

/*End*/

• Vinay Kumar

The above wouldn’t for all inputs. As it always stores max elements so far possible.

• Matheus dall rosa

could anyone tell me, if this implementation is correct?

/*begin*/
int n, nums[100], memo[100];
int lis( int i ){

if( i+1 == n ) return 1;

int m = 1;
for( ; i nums[i+1] )
m = max( m, memo[i+1] );

else m = max( m, memo[i+1]+1 );
}

return m;
}

int main( void ){

scanf(” %d”, &n);

for( int i = 0; i < n; i++ ){
scanf(" %d", &nums[i] );
}
memset( memo, -1, sizeof( memo ));

printf("%dn", lis( 0 ) );

return 0;
}

• ayush

In java (more efficient solution):

public static int[] solveUtil(int[] input, int n){

if(n==1)

return input;

int max=0;

int index = 0;

int[] lis = new int[input.length];

lis[0] = input[0];

for (int i = 1; i max){

max=input[i];

lis[++index]=input[i];

}

}

return lis;

}

• kx

This is wrong…

• Guest
• Ven Karri

The code above is wrong!!

Find the correct code here:
https://github.com/imperialguy/algorithms/blob/master/dynamic.py

• sp1rs

This is the version of code in java..

public class LongestIncreasingSubsequence{

public static int arr[];

public static void main(String[] args){

arr=new int[]{10, 22, 9, 33, 21, 50, 41, 60, 80,100}; // Array length assume to be 10 ( It can be anything)

System.out.println(find_list(arr,10));

}

public static int find_list(int a[],int len){

int list[]=new int[10];

for(int i=1;i<len;i++){

for(int j=0;j<i;j++){

if(a[j]<a[i] && list[i]<list[j]+1){

list[i]+=1;

}

}

}

return list[len-1]+1;

}

}

• Bala

Does your code work for 10,1,2,3,4,5?
I think ur code assumes LIS starts with first position of the sequence

Thanks for finding out the bug , I corrected it to make work with all kinds of series . Check the same link again !

• kx

‘your code assumes LIS starts with first position of the sequence’ — That was not the issue with your code (If the code at above link is still good). I think your code doesn’t understand the ‘Longest Increasing Subsequence’.
For something like [11,12,13,14,15,1,2,3,16,17,18], longest common subsequence will be [11,12,13,14,15,16,17,18]. Above code will not find this.

• Ven Karri

LIS is not the same as longest contiguous increasing subsequence. Your program returns the longest contiguous increasing subsequence, but that wasn’t the question.

• ???

Non-recursive & recursive in same class, for comparing.

public class Solution {

int[] max;

int[] _max;

public int LIS(int[] s) {

max = new int[s.length];

_max = new int[s.length];

Arrays.fill(max, 1);

Arrays.fill(_max, 1);

for (int i = 1; i < s.length; i++) {

for (int j = 0; j s[j] && max[i] < max[j] + 1)

max[i] = max[j] + 1;

}

}

Arrays.sort(max);

//recursive method

_LIS(s, s.length);

Arrays.sort(_max);

//return max[s.length-1];

return _max[s.length-1];

}

public int _LIS(int[] s, int where){

if (where == 1)

return 1;

int length;

for (int i = 1; i _max[where-1] && s[i-1] < s[where-1])

_max[where-1] = length +1;

}

return _max[where-1];

}

}

• leslie

implemented _lis in java and for some reason fails when negative numbers appear in the array — any suggestions?

static public int lis (int arr[], int n, int maxRef) {

if (n == 1) return 1;
int res, max = 1;

for (int i = 1; i < n; i ++) {
res = lis (arr, i, maxRef);
if (arr[i – 1] max) {
max = res + 1;
}
}

if (maxRef < max)
maxRef = max;

return max;
}

• aman

@Admin : Can we find the length of LIS using constant space only? Finding LIS wont be possible because output size isn’t constant.

• Pranali Yawalkar

#include

#include

#include

#include

using namespace std;

int a[50];

std::pair LUT[10];

int function(int i);

int main()

{

cout<<"enter a sequence"<<endl;

//int a[50];

for(int i=0;i>a[i];

LUT[0].first=a[0];

LUT[0].second=1;

function(1);

cout<LUT[i-1].first)

{

LUT[i].first=a[i];

LUT[i].second=LUT[i-1].second+1;

}

else

LUT[i]=LUT[i-1];

function(i+1);

}

}

• Guest

``` #include #include #include #include using namespace std; int a[50]; std::pair LUT[10]; int function(int i); int main() { cout<<"enter a sequence"<<endl; for(int i=0;i>a[i]; LUT[0].first=a[0]; LUT[0].second=1; function(1); cout<LUT[i-1].first) { LUT[i].first=a[i]; LUT[i].second=LUT[i-1].second+1; } else LUT[i]=LUT[i-1]; function(i+1); } } ```

• Raghvendra Singh

Hello Geeksforgeeks,

3,2,11,10,6,4,12,13,5,8

Although it is giving correct LIS which is 4 in this case but when i printed all the possible LIS of length 5 the result was wrong.

While i was checking the below two lines of code—-
if ( arr[i] > arr[j] && lis[i] < lis[j] + 1)

lis[i] = lis[j] + 1;

i found that for value 8 in input sequence the LIS which i am getting is—
3,6,5,8
and this is incorrect because 5 cannot come after 6 in LIS.

• neelabhsingh

Dear Raghvendra,

I tested your test case. As given lis[]. I print this array.

I am getting like this : list[]={1 1 2 2 2 2 3 4 3 4};

Length of LIS is 4

possible sub sequence are (3,2),(11,10,6,4) ,12,13 => length=4
(3,2), 4,(6,5),8=> length=4;
Not possible greater than 4.

• pavansrinivas

Following is O(n^3 ) Soln that prints all the sequences…What modifications can be made to make it run in O(n^2)??
``` int LIS(int[] a){ int fin_max = 1; for(int i=0;i<a.length;i++){ int max = 1; for(int j=i+1;j<a.length;j++){ int max_ele = a[i]; String kk = a[i]+"-"; for(int k = j;kmax_ele){ max++; kk +=a[k]+"-"; max_ele = a[k]; } } System.out.println(kk+"----"+max); if(max>fin_max){ fin_max = max; } max = 1; } } return fin_max; } ```

• Saket Kumar

// Java code time complexity O(n^2) & space complexity O(1)
public static int LIS(int[] arr){
int len=arr.length; int max_sub=0;

for(int i=0;i<len;i++){
int count=1; int value=arr[i];
for(int j=i;j<len;j++){
if(value<arr[j]){
count++;
value=arr[j];
}
if(max_sub<count)
max_sub=count;
}
}
return max_sub;
}

• Chandan Mittal

• neelabhsingh

I am getting like this : list[]={1 1 2 2 2 2 3 4 3 4};

Length of LIS is 4

• timus

thanks for ths…

• Subhransu Sahoo

I do not think we need to loop through to find the max, the max is already there in lis[n-1]

/* Pick maximum of all LIS values */
for ( i = 0; i < n; i++ )
if ( max < lis[i] )
max = lis[i];

Just return lis[n-1]

• sirui

lis[n-1] may not be the max because lis[i] is “the length of the LIS till index i such that arr[i] is part of LIS “. Notice that arr[i] is part of LIS!

• Sumit Monga

No, the loop to find max is necessary because elements are in unsorted order and lis[i] is the longest increasing subsequence upto arr[i] with arr[i] included.
Hope its clear now.

• anonymous

suppose given array is
10,22,9,33,21,50,41,40,60,55
LCS 1,2, 1, 3, 2, 4, 4, 4, 5, 5
Explanation 10 there is no one smaller than 10 so value is LCS(10)=1 ,
LCS(22)= 2, LSC(9)=1 because we have to keep in mind that 9 is also included but there is no number less than 9,LSC(33)= 3 because 33 is bigger than all three number 10,22, 9 so take max LCS , which is LCS(22)=2, LSC(33)=1+LSC(22) similar approach for all other …

• Shimpu

for ( i = 0; i < n; i++ )
if ( max < lis[i] )
max = lis[i];

is necessary suppose the list is 10,22,9,33,21
lis values are 1,2,1,3,2
its lis[n-1] value is 2 ..which is incorrect…as it clearly shows ans is 3…so we hav to pick max frm lis…Hope you got the point….

• ramneek garg

#include
int max(int a,int b)
{
if(a>b)
return a;
else
return b;
}
int subseq(int i,int arr[])
{
static int longest[100];
int j,p=-1;
for(j=0;jarr[i])
{
p=max(p,1);
}
else
{
if(longest[j]==0)
{
p=max(subseq(j,arr),p);
}
else
{
p=max(longest[j],p);
}
}
}
longest[i]=p+1;
return longest[i];
}
void main()
{
int arr[]={10,22,9,33,21,50,41,60,80};
printf(“longest increasing subsequense is %d”,subseq((sizeof(arr)/sizeof(int)-1),arr));
}

• vinodhinic

How to extend this logic to print all the LIS?
For eg:
for input {10,22,9,33,21,50,41,40,60,55}
LIS would be [1, 2, 1, 3, 2, 4, 4, 4, 5, 5]
And output should be:
10,22,33,40,55
10,22,33,41,60
10,22,33,50,60
10,22,33,41,55
10,22,33,50,55
10,22,33,40,60

I have tried using collections in JAVA
http://ideone.com/H3zte5

But I would appreciate if someone could post a neat solution

• Vinodhini

Hi,
I need a solution that prints all the LIS of the given input. For Eg: for input {10,22,9,33,21,50,41,40,60,55} LIS array: [1, 2, 1, 3, 2, 4, 4, 4, 5, 5] The output should be:
10,22,33,40,55
10,22,33,41,60
10,22,33,50,60
10,22,33,41,55
10,22,33,50,55
10,22,33,40,60

I have tried in JAVA. (link: http://ideone.com/H3zte5 ) But to admit, it is pretty clumsy with all the collections and iterators. Could anyone provide solution that is simple? I am guessing we could use Graph and find the longest path. But I am nowhere near achieving the solution. Someone please help.

• G4GFan

/*

This prints length longest increasing subsequence (not necessarily contiguous)

{10,22,9,33,21,50,41,40,60,55} = 5

{10,22,33,50,60} = LIS

*/

#include

#include

#include

void printArray(int arr[], int len){

int i = 0;

while(i<len){

printf("%dt", arr[i]);

i++;

}

printf("n");

}

void printLis(int arr[], int lis[], int res[], int next, int index, int maxLength, int arrlen){

int i,j,k;

if(index == maxLength+1){

printArray(res,index);

return;

}

for(i=0;i0){

k = 0;

while(k lis[i]){

break;

}

else {

k++;

}

}

if(k == i){

res[next] = arr[i];

//printf(“%dn”, res[next]);

printLis(arr, lis, res, next+1, index+1, maxLength, arrlen);

}

}

}

}

}

void getSubsequence(int arr[], int len){

int max,i,j,k,max_index;

int* lis = (int*)malloc(sizeof(int)*len);

max = arr[0];

lis[0] = 1;

i=1;

max_index = 0;

while(i= max){

lis[i] = lis[max_index] + 1;

max = arr[i];

max_index = i;

}

else{

int k = 0;

int min_diff = abs(arr[i]-arr[0]);

int index = 0;

while(k<i){

int diff = abs(arr[i]-arr[k]);

if(diff < min_diff){

min_diff = diff;

index = k;

}

k++;

}

if(arr[i] < arr[index]){

lis[i] = lis[index];

}

else{

lis[i] = lis[index] + 1;

}

}

i++;

}

printArray(lis, len);

int* res = (int*)malloc(sizeof(int) * lis[max_index]);

//printf("%dn", lis[max_index]);

printLis(arr, lis, res, 0, 1, lis[max_index], len);

}

int main(){

int arr[] = {10,22,9,33,21,50,41,40,60,55};

getSubsequence(arr, 10);

int arr1[] = {9,33,21,50,40,60,55};

getSubsequence(arr1, 7);

return 0;

}

• innosam

http://innosamcodes.wordpress.com/2013/07/06/longest-increasing-subsequence/
Check out the blog, for a explanation with brevity.
I have also written code to print the LIS.

• Karan

Can somebody please explain why we need to check this [if (arr[i-1] max_ending_here)
max_ending_here = res + 1;
] condition?

• sah_

Yet another simple brute force O(n^3) solution..
It considers all possible continuous sub-sequences…

#include

using namespace std;
int main()
{
int arr[]={ 10, 22, 9, 33, 21, 50, 41, 60, 80 } ;
int big=0;
int curr=0;
int n=9;
for(int i=0;i

• Nikin Kumar Jain

Method to Print Longest Increasing Subsequence

``` ```
// LongestIncreasingSequence.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>

using namespace std;

void printLIS(int arr[], int lis[], int max, int n)
{
if(n < 0)
return;
if(lis[n] == max)
{
printLIS(arr, lis, max-1, n-1);
cout<<arr[n]<<" ";
}
else
{
printLIS(arr, lis, max, n-1);
}
}

int lis(int arr[], int n)
{
int count = 0;
int *lis = (int *)malloc(sizeof(int) * n);
int i, j, index;

for(int i=0;i<n;i++)
lis[i] = 1;

for(int i=1;i<n;i++)
for(int j = 0; j<i;j++)
{
if(arr[i] > arr[j] && lis[i] < lis[j] + 1)
{
lis[i] = lis[j] + 1;
index = i;
}
}
int max = lis[index];
cout<<endl;

printLIS(arr, lis, max, n-1);

free(lis);
return max;
}

int _tmain(int argc, _TCHAR* argv[])
{
int arr[] = {10,22,9,33,21,50,41,60};

cout<<endl<<"Longest Increasing Sequence: "<<lis(arr, sizeof(arr)/sizeof(arr[0]));
getchar();
return 0;
}

``` ```
• shubham

there is something wong in printing values as it is printing wrong for test case
{ 10, 22, 9, 33, 21, 50, 41, 60, 80 }
it should print{ 10,22,33, 50, 60, 80}
but it is giving {10,22,33 ,41 ,60 ,80}

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• shubham

//it should be like this

#include
#include
using namespace std;
void printLIS(int arr[], int lis[], int max, int n)
{
if(n 0;i–)
{
if(lis[n]==max && lis[n-1]==max && arr[n]<arr[n-1])
n=n-1;
else
break;
}
printLIS(arr, lis, max-1, n-1);
cout<<arr[n]<<" ";
}
else
{
printLIS(arr, lis, max, n-1);
}
}

void lis_length(int arr[],int m)
{
int lis[m+1];
int value[m+1];
fill(&lis[0],&lis[m],1);
for(int i=1;i<m;i++)
for(int j=0;jarr[j]&&lis[i]<lis[j]+1)
{ lis[i]=lis[j]+1;value[i]=arr[j];}

int max=*max_element(lis,lis+m);
cout<<max<>t;
while(t–)
{
int n;
cin>>n;
int a[n];
for(int i=0;i>a[i];

lis_length(a,n);
}
}

• shubham

#include
#include
using namespace std;
void printLIS(int arr[], int lis[], int max, int n)
{
if(n 0;i–)
{
if(lis[n]==max && lis[n-1]==max &&arr[n]<arr[n-1])
n=n-1;
else
break;
}
printLIS(arr, lis, max-1, n-1);
cout<<arr[n]<<" ";
}
else
{
printLIS(arr, lis, max, n-1);
}
}

void lis_length(int arr[],int m)
{
int lis[m+1];
int value[m+1];
fill(&lis[0],&lis[m],1);
for(int i=1;i<m;i++)
for(int j=0;jarr[j]&&lis[i]<lis[j]+1)
{ lis[i]=lis[j]+1;value[i]=arr[j];}

int max=*max_element(lis,lis+m);
cout<<max<>t;
while(t–)
{
int n;
cin>>n;
int a[n];
for(int i=0;i>a[i];

lis_length(a,n);
}
}

• aygul

Actually it not wrong. It is one of the LISs and there might be more than one.
If you extend the code by storing the max end points, with the help of max length you can print all LISs.

• mohitk

Hi,
I believe the above also doesnt work for the below input:
{10, 11, 12, 9, 8, 7, 5, 6 }

It would always select the last altered LIS value as max, which is not the case in above.
The algo returns 2 whereas correct should be 3.

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• Rohit

@mohitk : yea.. it would not print proper values whenever the last element in sequence is not maximum, so it just need to copy its max value calculation form geeksforgeeks solution(not to mention, with proper curly braces) instead of making “index = i” and it should work fine.

/* Pick maximum of all LIS values */
for ( i = 0; i < n; i++ ){
if ( max < lis[i] )
max = lis[i];
}

/* Paste your code here (You may delete these lines if not writing code) */

• mrn
``` ```
/* Paste your code here (You may delete these lines if not writing code) */
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++)
{
if(a[i] < a[i])
{
b[j]=max(b[j],b[i]+1);
if(maxim<b[j])
maxim=b[j];
prv[j]=i;
}
}
``` ```
• jatinjindalj

Hello Geeksforgeeks,

I tried to understand and code the solution in Java.
The below is the code and it looks a little simpler then what you have given.
Could not understand the purpose of max_ref.

Regards

public class lis
{
static int lis_(int[] in,int last)
{
if(last==1)
return 1;
int result,maxTillNow=1;
for(int i=1;i<last;i++)
{
result=lis_(in,i);
if(in[i-1]<in[last-1] && result+1>maxTillNow)
maxTillNow=result+1;
}
return maxTillNow;
}

public static void main(String args[])
{
int[] in={0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15};
System.out.println("lis:"+lis_(in,in.length));
}
}

• maverick

@GeeksforGeeks There is a minute bug in the recursive code above
in the line

if (arr[i-1] max_ending_here)

which should actually be

if (arr[i-1] max_ending_here)

/* Paste your code here (You may delete these lines if not writing code) */

public class LCS {
public LCS() {
super();
}
public static int LCS(int [] A, int current, int k){
if(current>=A.length)
return 0;
if(A[current]>k)
return max(1+LCS(A,current+1,A[current]),LCS(A,current+1,k));
else return LCS(A,current+1,A[current]);
}
public static int max(int a,int b){
return a>b?a:b;
}
public static void main(String [] args){
int [] A={10,22,9,33,21,50,41,60,80};
System.out.println( LCS(A,0,0));
}
}

• Saurabh Jain
``` ```
/* Paste your code here (You may delete these lines if not writing code) */
/**
*
* @author saurabh
*/
public class LongestIncreasingSubsequence
{
int a[];
public LongestIncreasingSubsequence()
{
Scanner sc = new Scanner(System.in);
int size = sc.nextInt();
a = new int[size];
for(int i=0; i<size; i++)
{
a[i] = sc.nextInt();
}
System.out.println("Initial Array : ");
this.printArray();
System.out.println("\nLongest Increasing SubSequence is : ");
this.printLongestSubSequence();
}

private void printArray()
{
for(int i=0; i<a.length; i++)
System.out.print(a[i]+" ");
}

private void printLongestSubSequence()
{
int max_len=1,len_so_far,init=0,l;
for(int i=0; i<a.length; i++)
{
len_so_far=1;
l = a[i];
for(int j=i+1; j<a.length; j++)
{
if(a[j]>l)
{
len_so_far++;
l = a[j];
}
}
if(max_len<len_so_far)
{
max_len = len_so_far;
init = i;
}
}
int count=1;
l = a[init];
System.out.print(a[init]+" ");
for(int i=init+1; i<a.length; i++)
if(a[i]>l)
{
System.out.print(a[i]+" ");
l = a[i];
count++;
}
System.out.println();
System.out.println("Length of Longest Increasing SubSequence is : "+count);
}

public static void main(String[] args)
{
LongestIncreasingSubsequence lis = new LongestIncreasingSubsequence();
}
}

``` ```
• Saurabh Jain

Time Complexity of this code is O(n*n) or O(n^2)…correct me if anything is wrong…..

• Saurabh Jain

I forgot to write…. import java.util.Scanner….so don’t forget to use it…

• swathi

Can you please explain how to print the sequence of the LIS. I am facing the difficulty when we have multiple sets of LIS. Thanks..

• Spock

Why is there a need to check lis[i] < lis[j] + 1 ??
I guess lis[i] will always be greater than lis[j] + 1.

• Shrey

@Spock : Consider for i=3; you have the arr array’s elements as {10,22,9,33}.Now for calculating lis array we compare 33 with 10 its ok then we compare 33 with 22 its again ok and at last 33 with 9,its ok but the given subsequence is not a longest increasing subsequence as 9<22.hence this check is required.

Correct me if i am wrong.

• supercooluku

What is the time complexity of the naive recursive solution of LIS and also tell me how to find the time complexity of such a recursive code…

• kartik

The time complexity of the Naive Recursive solution is O(2^(n-1)) (2 raise to the power n-1).

You can get the time complexity by taking some sample values. Like T(3) = 4, T(4) = 8, T(5) = 16.
You can also solve it by solving the following recurrence.
T(n) = T(n-1) + T(n-2) + .. T(1)
and T(1) is constant

• krishna

The problem “sum sum of the sub sequence”, cannot have O(nlogn).
Reason: if we encounter an element which is less than all the max heads we need to move the array completely to right by one and add one element there, is there any other logic that avoids this condition? i believe not.

• GeeksforGeeks

@venki & @sparco:
The recursive function “_lis(arr, n)” must return the length of LIS ending arr[n-1] so that the value can be used by caller in recursion. Also, we need length of LIS in overall array. The earlier implementaion had some issues as it was returning only one value. Thanks for pointing out the issues. We have updated the naive recursive implementaion now.

• Venki

@Sandeep, In the recursive program, the logic behind the comparison “if (arr[i-1] < arr[n-1])” is not clear.

Consider we are at an arbitrary position ‘i’, and want to find the length of LIS at i-th location. If we know the maximum length till (i-1)th element, and if (A[i] > A[i-1]) we simply extend the LIS length by one. Otherwise (i.e. (A[i] <= A[i-1])), the maximum length of LIS at i-th location is same as (i-1)th location.

Putting in code, I have the following piece of code,

int LIS(int A[], int l, int r)
{
if( (r – l + 1) == 1 )
return 1;

int curLen;
int maxLen = 1;
for( int i = l; i <= r; i++ )
{
curLen = LIS(A, l, i-1);

if( A[i] > A[i-1] )
curLen++;

MaxSampleAndHold(maxLen, curLen);
}

return maxLen;
}

It is slightly different from the recursive logic given in the post. Is there any counter example for the above code?

• sparco

@geeksforgeeks
In recursion logic ,
I dont get why ( how the below code1 works exactly as code2)

Code1 – as written in the page

``` ```
if (arr[i-1] < arr[n-1])
res++;
``` ```

is used

Code2

``` ```
if (arr[i-1] < arr[i])
res++;
``` ```

is not used according to notes

To make use of recursive calls, this function must return two things:
1) Length of LIS
2) Index of the last element in LIS (This is necessary as we need to compare
the last element for new LIS)

public class LongestIncreasingSubsequence {
private static int binarySearch(int a[], int x, int start, int end) {
int limit = end;
int mid = 0;
while (start < end) {
mid = (start + end) >> 1;
if (a[mid] <= x) {
start = mid + 1;
} else {
end = mid – 1;
}
}
if (a[start] <= x) {
return start;
}
return start – 1;
}

public static void getLongestIncreasingSubsequence(int a[]) {
int dp[] = new int[a.length + 1];
int memo[] = new int[a.length + 1];

dp[0] = 1;
memo[1] = a[0];
int maxSize = 1;
for (int i = 1; i < a.length; ++i) {
if (a[i] < memo[1]) {
memo[1] = a[i];
dp[i] = 1;
} else if (a[i] >= memo[maxSize]) {
++maxSize;
memo[maxSize] = a[i];
dp[i] = maxSize;
} else {
int k = binarySearch(memo, a[i], 1, maxSize);
memo[k + 1] = a[i];
dp[i] = k + 1;
}
}
System.out.print(maxSize + " :: ");
for (int i = 1; i <= maxSize; ++i) {
System.out.print(memo[i] + " ");
}
System.out.println();
}

public static void main(String args[]) {
getLongestIncreasingSubsequence(new int[]{10, 22, 9, 33, 21, 50, 41, 60});
getLongestIncreasingSubsequence(new int[]{10, 22, 9, 33, 21, 50, 41, 60, 80});
getLongestIncreasingSubsequence(new int[]{1, 1, 1, 1, 0, 0, 0, 0, 0});
getLongestIncreasingSubsequence(new int[]{0, 0, 0, 0, 0, 1, 1, 1, 1});
}
}

• Devanshkaushik

hey, @kartikaditya, i tried ur code in netbeans, it gave the following output,
while 33 should not be there i gues….

run:
5 :: 9 21 33 41 60
6 :: 9 21 33 41 60 80
5 :: 0 0 0 0 0
9 :: 0 0 0 0 0 1 1 1 1

and more in case 2, there is anotheer sequence 10,22,33,50,60,80 which also has length 6, so why onnly this is printed? plzz clearify…

• Devanshkaushik

hey, @kartikaditya, i tried ur code in netbeans, it gave the following output,
while 21 should not be there i gues….

run:
5 :: 9 21 33 41 60
6 :: 9 21 33 41 60 80
5 :: 0 0 0 0 0
9 :: 0 0 0 0 0 1 1 1 1

and more in case 2, there is anotheer sequence 10,22,33,50,60,80 which also has length 6, so why onnly this is printed? plzz clearify…

• Aashish Barnwal

One solution is the modified version of longest increasing sub-sequence.
Here,take the first string as the sequence given,
second string is the sorted order of the first string.
Now apply the LCS algorithm.

``` ```
/*
#include <stdio.h>
#define SIZE1 9
#define SIZE2 9

void lcs(char *s1,char *s2)
{
int l[SIZE1+1][SIZE2+1],i,j;
char path[SIZE1+1][SIZE2+1];
for(i=0;i<=SIZE1;i++)
l[i][0]=0;
for(i=0;i<=SIZE2;i++)
l[0][i]=0;

for(i=1;i<=SIZE1;i++)
for(j=1;j<=SIZE2;j++)
{
if(s1[i-1]==s2[j-1])
{
l[i][j]=l[i-1][j-1] + 1;
path[i][j]='D';
}
else if(l[i][j-1] > l[i-1][j])
{
l[i][j]=l[i][j-1];
path[i][j]='L';
}
else
{
l[i][j]=l[i-1][j];
path[i][j]='T';
}
}
i=SIZE1,j=SIZE2;
while(i>0 && j>0)
{
if(path[i][j]=='T')
i--;
else if(path[i][j]=='L')
j--;
else
{
printf("%c ",s1[i-1]);
i--,j--;
}
}
printf("\n");
/*for(i=0;i<=SIZE1;i++)
{
for(j=0;j<=SIZE2;j++)
printf("%d  ",l[i][j]);
printf("\n");
}	*/
}

int main()
{
char s1[SIZE1+1],s2[SIZE2+1];
printf("Enter String1 n String2 ");
scanf("%s%s",s1,s2);
lcs(s1,s2);
return 0;
}
*/
``` ```
• Venkatesh

Can some one help me how to print the increasing sequence?

• outkast

Recursive Solution fails for input
int arr[] = {6,7,8,9,1};

• outkast

The Length of LIS is 4(6,7,8,9) but the function returns 1.

• GeeksforGeeks

@outkast: Thanks for pointing this out. There were issues in the previous code. We have updated the code.

• Abhinav Kumar

The code given using simple recursive is not consistent as it dose not follow what the question asks.
To try just take input array :{10,22,4,5,6,9,33,50,60,80}

• @Abhinav Kumar: Thanks for pointing this out. The code doesn’t seem to work for this example. We will look into this and fix the code.

• @Abhinav Kumar: I have updated the code and it now works fine for the example given by you.

``` ```
/* A Naive recursive implementation of LIS problem */
#include<stdio.h>
#include<stdlib.h>

int lis( int arr[], int n )
{
int max = 1;
int ls;

/* Base case */
if(n == 1)
return max;

/* Recursively get LIS for all smaller elements on left side */
for(int i = 0; i < n - 1; i++)
{
if (arr[i] < arr[n-1])
{
ls = lis(arr, i+1) + 1;

/* Check if max needs to be updated */
if(ls > max)
max = ls;
}
}
return max;
}

/* Driver program to test above function */
int main()
{
int arr[] = {10,22,4,5,6,9,33,50,60,80};
int n = sizeof(arr)/sizeof(arr[0]);
printf("Length of LIS is %d\n", lis( arr, n ) );

getchar();
return 0;
}
``` ```
• Yueming

Try this {10,22,4,5,6,9,33,50,60,80,0}, it return 1!

``` ```
/* Paste your code here (You may delete these lines if not writing code) */
``` ```
• Sandeep

The code was further updated due to one more issue pointed by a user. The final code given in post works for your example.

``` ```
/* A Naive recursive implementation of LIS problem */
#include<stdio.h>
#include<stdlib.h>

/* To make use of recursive calls, this function must return two things:
1) Length of LIS
2) Index of the last element in LIS (This is necessary as we need to compare
the last element for new LIS)
*/

int lis( int arr[], int n )
{
/* Base case */
if(n == 1)
return 1;

int res, max = 1;

/* Recursively get LIS for all smaller elements on left side */
for(int i = 1; i < n; i++)
{
res = lis(arr, i);
if (arr[i-1] < arr[n-1])
res++;

/* Check if max needs to be updated */
if(res  > max)
max = res;
}
return max;
}

/* Driver program to test above function */
int main()
{
int arr[] = {10,22,4,5,6,9,33,50,60,80,0};
int n = sizeof(arr)/sizeof(arr[0]);
int max = lis( arr, n );
printf("Length of LIS is %d\n",  max);

getchar();
return 0;
}

``` ```
• KK123
• pucitian

i am soin my term paper on dp using lcs as an example……..i found this topic very interesting…..

• vignesh

In the above paragraph explaining optimal substructure i find something missing.
Let [0..n-1] be the input array and L(i) be the length of the LIS till index i including ith index then L(i) can be recursively written as.
LIS(i) = { 1 + Max ( LIS(j) ) } where j < i and arr[j] < arr[i] and if there is no such j then “LIS(i) = 1″
It should be “Lis(i) = Lis(i-1)“.
For instance if 10, 8, 6, 11, 5 is the input array.
Lis(0) = 1 // 10 alone
Lis(1) = 1 // 8 or 10 alone
Lis(2) = 1 // 6 or 8 or 10 alone
Lis(3) = 2 // {10,11 } or {8,11} or {6,11}
Lis(4) = 2 // {10,11 } or {8,11} or {6,11} though 5 is not included. but according to t recurrence relation mentioned in the above paragraph Lis(4) will be one which is erroneous against t base assumption tat Lis(i) represents longest increasing subsequence including i.

• @vignesh: Thanks for pointing this out. There was a typo in explanation, I have corrected it so that it matches with the implementation. Let me know if it looks fine now.

• vignesh

@sandeep :- my understanding about the recurrence relation was wrong. Lis(i) represents longest subsequence ending in i(i mistook it as including i). so recurrence relation is right. After populating the Lis array. One should find t maximum in Lis[] to get LIS. Well in nlogn approach they maintain a separate array to keep track of individual elements as well.

• SDK

I still don’t get geeksforgeeks explanation that why LIS[i] =1 … it should be LIS[i]=LIS[i-1] if the conditions are not met…..

I think the following code works plz check.

``` ```
#include<stdio.h>
#include<stdlib.h>
int maxof(int *a,int n){
int i=0;
int max=a[0];
for(i=0;i<n;i++){
if(a[i]>max) max=a[i];
}
return i;
}
int lis(int arr[],int n){

int i,j,index;
int*ls=(int*) calloc(sizeof(int),n);

ls[0]=1;  //if it contains only one element;

for(i=1;i<n;i++){
for(j=0;j<i;j++){

index = maxof(ls,i-1);
if(arr[i]>arr[index])
ls[i]=1 + ls[index];
else
ls[i] = ls[i-1];
}
}

return ls[n-1];
}

int main()
{
int arr[] = {10,20,11,12,22,44,62,8,82};
int n = sizeof(arr)/sizeof(arr[0]);
printf("Length of LIS is %d\n", lis( arr, n ) );

getchar();
return 0;
}
``` ```

plz explain why they have taken LIS[i]=1

• GeeksforGeeks

@SDK: Every element of input array is LIS of length 1. That is why we have initial values in LIS as 1.

• martin

@GeeksforGeeks Note that the time complexity of the above Dynamic Programmig (DP) solution is O(n^2) and there is a O(nLogn) solution for the LIS problem (see this). We have not discussed the nLogn solution here as the purpose of this post is to explain Dynamic Programming with a simple example.

• @Martin, Thanks for your comments, we will soon have the nlogn solution of LIS as a post under special category.

• reema

@sandeep its will just return the length of LIS not LIs itself , can you post the solution for that itself or please tell me wht modification we need to do for that to print LIS from above array ?

• satya

@GeeksforGeeks..Keep Posting FAQ DP Asked problems ..keep it up..

• Vinay

plz how are “Longest Increasing Subsequence problem” and “Maximum Sorted(ascending) Subsequence problem” diffrent?

• giri

Good job. I find following practice problems also very useful.

http://people.csail.mit.edu/bdean/6.046/dp/

• tk

Can someone explain the nLogn approach for LIS?

• GeeksforGeeks

@tk: We will soon publish a separate post for nLogn solution of LIS problem.

• Anand
• GeeksforGeeks

@venki: Thanks for pointing this out. I have corrected the typo.

• reema

@GeeksForGeeks its will just return the length of LIS not LIs itself , can you post the solution for that itself or please tell me wht modification we need to do for that to print LIS from above array ?