Longest Decreasing Subsequence
Given an array of N integers, find the length of the longest subsequence of a given sequence such that all elements of the subsequence are sorted in strictly decreasing order.
Examples:
Input: arr[] = [15, 27, 14, 38, 63, 55, 46, 65, 85]
Output: 3
Explanation: The longest decreasing subsequence is {63, 55, 46}
Input: arr[] = {50, 3, 10, 7, 40, 80}
Output: 3
Explanation: The longest decreasing subsequence is {50, 10, 7}
The problem can be solved using Dynamic Programming
Optimal Substructure:
Let arr[0…n-1] be the input array and lds[i] be the length of the LDS ending at index i such that arr[i] is the last element of the LDS.
Then, lds[i] can be recursively written as:
lds[i] = 1 + max(lds[j]) where i > j > 0 and arr[j] > arr[i] or
lds[i] = 1, if no such j exists.
To find the LDS for a given array, we need to return max(lds[i]) where n > i > 0.
C++
#include <bits/stdc++.h>
using namespace std;
int lds( int arr[], int n)
{
int lds[n];
int i, j, max = 0;
for (i = 0; i < n; i++)
lds[i] = 1;
for (i = 1; i < n; i++)
for (j = 0; j < i; j++)
if (arr[i] < arr[j] && lds[i] < lds[j] + 1)
lds[i] = lds[j] + 1;
for (i = 0; i < n; i++)
if (max < lds[i])
max = lds[i];
return max;
}
int main()
{
int arr[] = { 15, 27, 14, 38, 63, 55, 46, 65, 85 };
int n = sizeof (arr) / sizeof (arr[0]);
cout << "Length of LDS is " << lds(arr, n);
return 0;
}
|
Java
import java.io.*;
class GFG
{
static int lds( int arr[], int n)
{
int lds[] = new int [n];
int i, j, max = 0 ;
for (i = 0 ; i < n; i++)
lds[i] = 1 ;
for (i = 1 ; i < n; i++)
for (j = 0 ; j < i; j++)
if (arr[i] < arr[j] &&
lds[i] < lds[j] + 1 )
lds[i] = lds[j] + 1 ;
for (i = 0 ; i < n; i++)
if (max < lds[i])
max = lds[i];
return max;
}
public static void main (String[] args)
{
int arr[] = { 15 , 27 , 14 , 38 ,
63 , 55 , 46 , 65 , 85 };
int n = arr.length;
System.out.print( "Length of LDS is " +
lds(arr, n));
}
}
|
Python 3
def lds(arr, n):
lds = [ 0 ] * n
max = 0
for i in range (n):
lds[i] = 1
for i in range ( 1 , n):
for j in range (i):
if (arr[i] < arr[j] and
lds[i] < lds[j] + 1 ):
lds[i] = lds[j] + 1
for i in range (n):
if ( max < lds[i]):
max = lds[i]
return max
if __name__ = = "__main__" :
arr = [ 15 , 27 , 14 , 38 ,
63 , 55 , 46 , 65 , 85 ]
n = len (arr)
print ( "Length of LDS is" , lds(arr, n))
|
C#
using System;
class GFG
{
static int lds( int []arr, int n)
{
int []lds = new int [n];
int i, j, max = 0;
for (i = 0; i < n; i++)
lds[i] = 1;
for (i = 1; i < n; i++)
for (j = 0; j < i; j++)
if (arr[i] < arr[j] &&
lds[i] < lds[j] + 1)
lds[i] = lds[j] + 1;
for (i = 0; i < n; i++)
if (max < lds[i])
max = lds[i];
return max;
}
public static void Main ()
{
int []arr = { 15, 27, 14, 38,
63, 55, 46, 65, 85 };
int n = arr.Length;
Console.Write( "Length of LDS is " +
lds(arr, n));
}
}
|
PHP
<?php
function lds( $arr , $n )
{
$lds = array ();
$i ; $j ; $max = 0;
for ( $i = 0; $i < $n ; $i ++)
$lds [ $i ] = 1;
for ( $i = 1; $i < $n ; $i ++)
for ( $j = 0; $j < $i ; $j ++)
if ( $arr [ $i ] < $arr [ $j ] and
$lds [ $i ] < $lds [ $j ] + 1)
{
$lds [ $i ] = $lds [ $j ] + 1;
}
for ( $i = 0; $i < $n ; $i ++)
if ( $max < $lds [ $i ])
$max = $lds [ $i ];
return $max ;
}
$arr = array (15, 27, 14, 38, 63,
55, 46, 65, 85);
$n = count ( $arr );
echo "Length of LDS is " ,
lds( $arr , $n );
?>
|
Javascript
<script>
function lds(arr,n)
{
let lds = new Array(n);
let i, j, max = 0;
for (i = 0; i < n; i++)
lds[i] = 1;
for (i = 1; i < n; i++)
for (j = 0; j < i; j++)
if (arr[i] < arr[j] &&
lds[i] < lds[j] + 1)
lds[i] = lds[j] + 1;
for (i = 0; i < n; i++)
if (max < lds[i])
max = lds[i];
return max;
}
let arr=[15, 27, 14, 38,
63, 55, 46, 65, 85 ];
let n = arr.length;
document.write( "Length of LDS is " +
lds(arr, n));
</script>
|
Output :
Length of LDS is 3
Time Complexity: O(n2)
Auxiliary Space: O(n)
Related Article: https://www.geeksforgeeks.org/longest-increasing-subsequence/
Longest Decreasing Subsequence in O(n*log(n)) :
Another approach to finding the Longest Decreasing Subsequence is using the Longest Increasing Subsequence approach in n*log(n) complexity. Here is the link to find the details of the approach with O(n*log(n)) complexity https://www.geeksforgeeks.org/longest-monotonically-increasing-subsequence-size-n-log-n/.
We can observe that the length of the Longest Decreasing Subsequence of any array is same as the length of the Longest Increasing Subsequence of that array if we multiply all elements by -1.
For example:
arr[] = [15, 27, 14, 38, 63, 55, 46, 65, 85]
then the length of longest decreasing subsequence of this array is same as length of longest increasing subsequence of arr[]=[-15, -27, -14, -38, -63, -55, -46, -65, -85]
In both cases the length is 3.
Steps to solve this problem:
1. Check if array is zero than return zero.
2. Declare a vector tail of array size.
3. Declare a variable length=1.
4. Initialize tail[0]=v[0].
5. Iterate through i=1 till size of array:
*Initialize auto b=tail.begin and e=tail.begin+length.
*Initialize auto it to lower bound of v[i].
*Check if it is equal to tail.begin+length than tail[length++]=v[i].
*Else update value at it =v[i].
6. Return length.
Below is the code of the above approach.
C++
#include <bits/stdc++.h>
using namespace std;
int LongestIncreasingSubsequenceLength(vector< int >& v)
{
if (v.size() == 0)
return 0;
vector< int > tail(v.size(), 0);
int length = 1;
tail[0] = v[0];
for ( int i = 1; i < v.size(); i++) {
auto b = tail.begin(), e = tail.begin() + length;
auto it = lower_bound(b, e, v[i]);
if (it == tail.begin() + length)
tail[length++] = v[i];
else
*it = v[i];
}
return length;
}
int main()
{
vector< int > v{ 15, 27, 14, 38, 63, 55, 46, 65, 85 };
int n=v.size();
for ( int i=0;i<n;i++)
{
v[i]=-1*v[i];
}
cout
<< "Length of Longest Decreasing Subsequence is "
<< LongestIncreasingSubsequenceLength(v);
return 0;
}
|
Java
import java.io.*;
import java.lang.Math;
import java.util.*;
class LIS {
static int LongestIncreasingSubsequenceLength( int v[])
{
if (v.length == 0 )
return 0 ;
int [] tail = new int [v.length];
int length = 1 ;
tail[ 0 ] = v[ 0 ];
for ( int i = 1 ; i < v.length; i++) {
if (v[i] > tail[length - 1 ]) {
tail[length++] = v[i];
}
else {
int idx = Arrays.binarySearch(
tail, 0 , length - 1 , v[i]);
if (idx < 0 )
idx = - 1 * idx - 1 ;
tail[idx] = v[i];
}
}
return length;
}
public static void main(String[] args)
{
int v[] = { 2 , 5 , 3 , 7 , 11 , 8 , 10 , 13 , 6 };
int n=v.length;
for ( int i= 0 ;i<n;i++)
{
v[i]=- 1 *v[i];
}
System.out.println(
"Length of Longest Decreasing Subsequence is "
+ LongestIncreasingSubsequenceLength(v));
}
}
|
Python3
from bisect import bisect_left
def LongestIncreasingSubsequenceLength(v):
n = len (v)
if n = = 0 :
return 0
tail = [ 0 ] * n
length = 1
tail[ 0 ] = v[ 0 ]
for i in range ( 1 , n):
j = bisect_left(tail, v[i], 0 , length)
if j = = length:
tail[length] = v[i]
length + = 1
else :
tail[j] = v[i]
return length
v = [ 15 , 27 , 14 , 38 , 63 , 55 , 46 , 65 , 85 ]
v = [ - x for x in v]
print ( "Length of Longest Decreasing Subsequence is" , LongestIncreasingSubsequenceLength(v))
|
C#
using System;
using System.Linq;
class LIS {
static int LongestIncreasingSubsequenceLength( int [] v)
{
if (v.Length == 0)
return 0;
int [] tail = new int [v.Length];
int length = 1;
tail[0] = v[0];
for ( int i = 1; i < v.Length; i++) {
if (v[i] > tail[length - 1]) {
tail[length++] = v[i];
}
else {
int idx = Array.BinarySearch(
tail, 0, length - 1, v[i]);
if (idx < 0)
idx = ~idx;
tail[idx] = v[i];
}
}
return length;
}
public static void Main( string [] args)
{
int [] v = { 2, 5, 3, 7, 11, 8, 10, 13, 6 };
int n = v.Length;
for ( int i = 0; i < n; i++) {
v[i] = -1 * v[i];
}
Console.WriteLine(
"Length of Longest Decreasing Subsequence is "
+ LongestIncreasingSubsequenceLength(v));
}
}
|
Javascript
function LongestIncreasingSubsequenceLength(v) {
if (v.length === 0) {
return 0;
}
const tail = new Array(v.length).fill(0);
let length = 1;
tail[0] = v[0];
for (let i = 1; i < v.length; i++) {
let b = 0, e = length;
let mid;
while (b < e) {
mid = Math.floor((b + e) / 2);
if (tail[mid] < v[i]) {
b = mid + 1;
} else {
e = mid;
}
}
if (b === length) {
tail[length++] = v[i];
} else {
tail[b] = v[i];
}
}
return length;
}
let v = [15, 27, 14, 38, 63, 55, 46, 65, 85];
let n = v.length;
for (let i = 0; i < n; i++) {
v[i] = -v[i];
}
console.log( "Length of Longest Decreasing Subsequence is " +
LongestIncreasingSubsequenceLength(v));
|
Output
Length of Longest Decreasing Subsequence is 3
Time Complexity: O(n*logn)
Auxiliary Space: O(n)
Last Updated :
28 Feb, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...