Length of longest strict bitonic subsequence
Last Updated :
12 Feb, 2023
Given an array arr[] containing n integers. The problem is to find the length of the longest strict bitonic subsequence. A subsequence is called strict bitonic if it is first increasing and then decreasing with the condition that in both the increasing and decreasing parts the absolute difference between adjacents is 1 only. A sequence, sorted in increasing order is considered Bitonic with the decreasing part as empty. Similarly, decreasing order sequence is considered Bitonic with the increasing part as empty.
Examples:
Input : arr[] = {1, 5, 2, 3, 4, 5, 3, 2}
Output : 6
The Longest Strict Bitonic Subsequence is:
{1, 2, 3, 4, 3, 2}.
Input : arr[] = {1, 2, 5, 3, 6, 7, 4, 6, 5}
Output : 5
Method 1: The problem could be solved using the concept of finding the longest bitonic subsequence. The only condition that needs to be maintained is that the adjacents should have a difference of 1 only. It has a time complexity of O(n2).
- We need to construct two arrays lis[] and lds[] using the Dynamic Programming solution of the LIS problem.
- lis[i] stores the length of the Longest Increasing subsequence ending with arr[i].
- lds[i] stores the length of the longest Decreasing subsequence starting from arr[i].
- Finally, we need to return the max value of lis[i] + lds[i] – 1 where i is from 0 to n-1.
Below is the implementation of the above approach:
C++
#include <stdio.h>
#include <stdlib.h>
int lbs( int arr[], int n)
{
int i, j;
int * lis = new int [n];
for (i = 0; i < n; i++)
lis[i] = 1;
for (i = 1; i < n; i++)
for (j = 0; j < i; j++)
if (arr[i] > arr[j] && abs (arr[i] - arr[j] == 1)
&& lis[i] < lis[j] + 1)
lis[i] = lis[j] + 1;
int * lds = new int [n];
for (i = 0; i < n; i++)
lds[i] = 1;
for (i = n - 2; i >= 0; i--)
for (j = n - 1; j > i; j--)
if (arr[i] > arr[j] && abs (arr[i] - arr[j] == 1)
&& lds[i] < lds[j] + 1)
lds[i] = lds[j] + 1;
int max = lis[0] + lds[0] - 1;
for (i = 1; i < n; i++)
if (lis[i] + lds[i] - 1 > max)
max = lis[i] + lds[i] - 1;
return max;
}
int main()
{
int arr[] = { 1, 5, 2, 3, 4, 5, 3, 2 };
int n = sizeof (arr) / sizeof (arr[0]);
printf ( "Length of LBS is %d\n" , lbs(arr, n));
return 0;
}
|
Python3
def lbs(arr):
n = len (arr)
lis = [ 1 ] * n
for i in range ( 1 , n):
for j in range ( 0 , i):
if arr[i] > arr[j] and abs (arr[i] - arr[j]) = = 1 and lis[i] < lis[j] + 1 :
lis[i] = lis[j] + 1
lds = [ 1 ] * n
for i in range (n - 2 , - 1 , - 1 ):
for j in range (n - 1 , i, - 1 ):
if arr[i] > arr[j] and abs (arr[i] - arr[j]) = = 1 and lds[i] < lds[j] + 1 :
lds[i] = lds[j] + 1
max_val = lis[ 0 ] + lds[ 0 ] - 1
for i in range ( 1 , n):
max_val = max (max_val, lis[i] + lds[i] - 1 )
return max_val
arr = [ 1 , 5 , 2 , 3 , 4 , 5 , 3 , 2 ]
print ( "Length of LBS is" , lbs(arr))
|
C#
using System;
using System.Collections.Generic;
class Gfg
{
static int lbs( int [] arr, int n)
{
int i, j;
int [] lis = new int [n];
for (i = 0; i < n; i++)
lis[i] = 1;
for (i = 1; i < n; i++)
for (j = 0; j < i; j++)
if (arr[i] > arr[j] && Math.Abs(arr[i] - arr[j]) == 1 && lis[i] < lis[j] + 1)
lis[i] = lis[j] + 1;
int [] lds = new int [n];
for (i = 0; i < n; i++)
lds[i] = 1;
for (i = n - 2; i >= 0; i--)
for (j = n - 1; j > i; j--)
if (arr[i] > arr[j] && Math.Abs(arr[i] - arr[j]) == 1 && lds[i] < lds[j] + 1)
lds[i] = lds[j] + 1;
int max = lis[0] + lds[0] - 1;
for (i = 1; i < n; i++)
if (lis[i] + lds[i] - 1 > max)
max = lis[i] + lds[i] - 1;
return max;
}
public static void Main( string [] args)
{
int [] arr = { 1, 5, 2, 3, 4, 5, 3, 2 };
int n = arr.Length;
Console.Write( "Length of LBS is " + lbs(arr, n));
}
}
|
Javascript
function lbs(arr, n)
{
let i, j;
let lis = new Array(n);
for (i = 0; i < n; i++)
lis[i] = 1;
for (i = 1; i < n; i++)
for (j = 0; j < i; j++)
if (arr[i] > arr[j] && Math.abs(arr[i] - arr[j] == 1)
&& lis[i] < lis[j] + 1)
lis[i] = lis[j] + 1;
let lds = new Array(n);
for (i = 0; i < n; i++)
lds[i] = 1;
for (i = n - 2; i >= 0; i--)
for (j = n - 1; j > i; j--)
if (arr[i] > arr[j] && Math.abs(arr[i] - arr[j] == 1)
&& lds[i] < lds[j] + 1)
lds[i] = lds[j] + 1;
let max = lis[0] + lds[0] - 1;
for (i = 1; i < n; i++)
if (lis[i] + lds[i] - 1 > max)
max = lis[i] + lds[i] - 1;
return max;
}
let arr = [ 1, 5, 2, 3, 4, 5, 3, 2 ];
let n = arr.length;
console.log( "Length of LBS is " , lbs(arr, n));
|
Java
import java.util.*;
import java.lang.Math;
class GfG
{
static int lbs( int arr[], int n)
{
int i, j;
int lis[] = new int [n];
for (i = 0 ; i < n; i++)
lis[i] = 1 ;
for (i = 1 ; i < n; i++)
for (j = 0 ; j < i; j++)
if (arr[i] > arr[j] && Math.abs(arr[i] - arr[j]) == 1 && lis[i] < lis[j] + 1 )
lis[i] = lis[j] + 1 ;
int lds[] = new int [n];
for (i = 0 ; i < n; i++)
lds[i] = 1 ;
for (i = n - 2 ; i >= 0 ; i--)
for (j = n - 1 ; j > i; j--)
if (arr[i] > arr[j] && Math.abs(arr[i] - arr[j]) == 1 && lds[i] < lds[j] + 1 )
lds[i] = lds[j] + 1 ;
int max = lis[ 0 ] + lds[ 0 ] - 1 ;
for (i = 1 ; i < n; i++)
if (lis[i] + lds[i] - 1 > max)
max = lis[i] + lds[i] - 1 ;
return max;
}
public static void main(String[] args)
{
int arr[] = { 1 , 5 , 2 , 3 , 4 , 5 , 3 , 2 };
int n = arr.length;
System.out.println( "Length of LBS is " + lbs(arr, n));
}
}
|
Output
Length of LBS is 6
Time Complexity: O(n*n)
Auxiliary Space: O(n)
Method 2 (Efficient Approach):
The idea is to create two hash maps inc and dcr having tuples in the form (ele, len), where len denotes the length of the longest increasing subsequence ending with the element ele in map inc and length of the longest decreasing subsequence starting with element ele in map dcr respectively. Also create two arrays len_inc[] and len_dcr[] where len_inc[i] represents the length of the largest increasing subsequence ending with element arr[i] and len_dcr[i] represents the length of the largest decreasing subsequence starting with element arr[i]. Now, for each element arr[i] we can find the length of the value (arr[i]-1) if it exists in the hash table inc. Let this value be v (initially v will be 0).
Now, the length of longest increasing subsequence ending with arr[i] would be v+1. Update this length along with the element arr[i] in the hash table inc and in the array len_inc[] at respective index i. Now, traversing the array from right to left we can similarly fill the hash table dcr and array len_dcr[] for longest decreasing subsequence. Finally, for each element arr[i] we calculate (len_inc[i] + len_dcr[i] – 1) and return the maximum value.
Note: Here increasing and decreasing subsequences only mean that the difference between adjacent elements is 1 only.
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
int longLenStrictBitonicSub( int arr[], int n)
{
unordered_map< int , int > inc, dcr;
int len_inc[n], len_dcr[n];
int longLen = 0;
for ( int i=0; i<n; i++)
{
int len = 0;
if (inc.find(arr[i]-1) != inc.end())
len = inc[arr[i]-1];
inc[arr[i]] = len_inc[i] = len + 1;
}
for ( int i=n-1; i>=0; i--)
{
int len = 0;
if (dcr.find(arr[i]-1) != dcr.end())
len = dcr[arr[i]-1];
dcr[arr[i]] = len_dcr[i] = len + 1;
}
for ( int i=0; i<n; i++)
if (longLen < (len_inc[i] + len_dcr[i] - 1))
longLen = len_inc[i] + len_dcr[i] - 1;
return longLen;
}
int main()
{
int arr[] = {1, 5, 2, 3, 4, 5, 3, 2};
int n = sizeof (arr) / sizeof (arr[0]);
cout << "Longest length strict bitonic subsequence = "
<< longLenStrictBitonicSub(arr, n);
return 0;
}
|
Java
import java.util.*;
class GfG
{
static int longLenStrictBitonicSub( int arr[], int n)
{
HashMap<Integer, Integer> inc = new HashMap<Integer, Integer> ();
HashMap<Integer, Integer> dcr = new HashMap<Integer, Integer> ();
int len_inc[] = new int [n];
int len_dcr[] = new int [n];
int longLen = 0 ;
for ( int i = 0 ; i < n; i++)
{
int len = 0 ;
if (inc.containsKey(arr[i] - 1 ))
len = inc.get(arr[i] - 1 );
len_inc[i] = len + 1 ;
inc.put(arr[i], len_inc[i]);
}
for ( int i = n - 1 ; i >= 0 ; i--)
{
int len = 0 ;
if (dcr.containsKey(arr[i] - 1 ))
len = dcr.get(arr[i] - 1 );
len_dcr[i] = len + 1 ;
dcr.put(arr[i], len_dcr[i]);
}
for ( int i = 0 ; i < n; i++)
if (longLen < (len_inc[i] + len_dcr[i] - 1 ))
longLen = len_inc[i] + len_dcr[i] - 1 ;
return longLen;
}
public static void main(String[] args)
{
int arr[] = { 1 , 5 , 2 , 3 , 4 , 5 , 3 , 2 };
int n = arr.length;
System.out.println( "Longest length strict " +
"bitonic subsequence = " +
longLenStrictBitonicSub(arr, n));
}
}
|
Python3
def longLenStrictBitonicSub(arr, n):
inc, dcr = dict (), dict ()
len_inc, len_dcr = [ 0 ] * n, [ 0 ] * n
longLen = 0
for i in range (n):
len = 0
if inc.get(arr[i] - 1 ) in inc.values():
len = inc.get(arr[i] - 1 )
inc[arr[i]] = len_inc[i] = len + 1
for i in range (n - 1 , - 1 , - 1 ):
len = 0
if dcr.get(arr[i] - 1 ) in dcr.values():
len = dcr.get(arr[i] - 1 )
dcr[arr[i]] = len_dcr[i] = len + 1
for i in range (n):
if longLen < (len_inc[i] + len_dcr[i] - 1 ):
longLen = len_inc[i] + len_dcr[i] - 1
return longLen
if __name__ = = "__main__" :
arr = [ 1 , 5 , 2 , 3 , 4 , 5 , 3 , 2 ]
n = len (arr)
print ( "Longest length strict bitonic subsequence =" ,
longLenStrictBitonicSub(arr, n))
|
C#
using System;
using System.Collections.Generic;
class GfG
{
static int longLenStrictBitonicSub( int []arr, int n)
{
Dictionary< int , int > inc = new Dictionary< int , int > ();
Dictionary< int , int > dcr = new Dictionary< int , int > ();
int []len_inc = new int [n];
int []len_dcr = new int [n];
int longLen = 0;
for ( int i = 0; i < n; i++)
{
int len = 0;
if (inc.ContainsKey(arr[i] - 1))
len = inc[arr[i] - 1];
len_inc[i] = len + 1;
if (inc.ContainsKey(arr[i]))
{
inc.Remove(arr[i]);
inc.Add(arr[i], len_inc[i]);
}
else
inc.Add(arr[i], len_inc[i]);
}
for ( int i = n - 1; i >= 0; i--)
{
int len = 0;
if (dcr.ContainsKey(arr[i] - 1))
len = dcr[arr[i] - 1];
len_dcr[i] = len + 1;
if (dcr.ContainsKey(arr[i]))
{
dcr.Remove(arr[i]);
dcr.Add(arr[i], len_dcr[i]);
}
else
dcr.Add(arr[i], len_dcr[i]);
}
for ( int i = 0; i < n; i++)
if (longLen < (len_inc[i] + len_dcr[i] - 1))
longLen = len_inc[i] + len_dcr[i] - 1;
return longLen;
}
public static void Main(String[] args)
{
int []arr = {1, 5, 2, 3, 4, 5, 3, 2};
int n = arr.Length;
Console.WriteLine( "Longest length strict " +
"bitonic subsequence = " +
longLenStrictBitonicSub(arr, n));
}
}
|
Javascript
<script>
function longLenStrictBitonicSub(arr, n)
{
var inc = new Map(), dcr = new Map();
var len_inc = Array(n), len_dcr = Array(n);
var longLen = 0;
for ( var i=0; i<n; i++)
{
var len = 0;
if (inc.has(arr[i]-1))
len = inc.get(arr[i]-1);
len_inc[i] = len + 1;
inc.set(arr[i], len_inc[i]);
}
for ( var i=n-1; i>=0; i--)
{
var len = 0;
if (dcr.has(arr[i]-1))
len = dcr.get(arr[i]-1);
len_dcr[i] = len + 1;
dcr.set(arr[i], len_dcr[i]);
}
for ( var i=0; i<n; i++)
if (longLen < (len_inc[i] + len_dcr[i] - 1))
longLen = len_inc[i] + len_dcr[i] - 1;
return longLen;
}
var arr = [1, 5, 2, 3, 4, 5, 3, 2];
var n = arr.length;
document.write( "Longest length strict bitonic subsequence = "
+ longLenStrictBitonicSub(arr, n));
</script>
|
Output
Longest length strict bitonic subsequence = 6
Time Complexity: O(n).
Auxiliary Space: O(n).
Please Login to comment...