Given an array arr[] of size N, the task is to print the longest bitonic subsequence of the given array.
Note: If more than one solution exit then prints anyone solution.
Examples:
Input: arr[] = {1, 11, 2, 10, 4, 5, 2, 1}
Output: 1 11 10 5 2 1
Explanation:
All possible longest bitonic subsequences from the above array are {1, 2, 10, 4, 2, 1}, {1, 11, 10, 5, 2, 1}, {1, 2, 4, 5, 2, 1}.
Therefore, print any of them to obtain the answer.Input: arr[] = {80, 60, 30, 40, 20, 10}
Output: 80 60 30 20 10
Dynamic Programming Approach using Extra Space: Refer to the previous article for the 2D Dynamic programming approach to solve the problem.
Time Complexity: O(N2)
Auxiliary Space: O(N2)
Space-Optimized Approach: The auxiliary space used for the above approach can be optimized by using 1D Dynamic Programming. Follow the below steps to solve the problem.
- Create two arrays lis[] and lds[] to store, at every ith Index, the length of the longest increasing and decreasing subsequences ending with the element arr[i] respectively.
- Once computed, find the ith index which contains the maximum value of lis[i] + lds[i] – 1
- Create res[] to store all the elements of the longest bitonic sequence in decreasing order of elements followed by increasing order of elements.
- Print the res[] array.
Below is the implement the above approach:
// C++ Program to implement // the above approach #include <bits/stdc++.h> using namespace std;
// Function to print the longest // bitonic subsequence void printRes(vector< int >& res)
{ int n = res.size();
for ( int i = 0; i < n; i++) {
cout << res[i] << " " ;
}
} // Function to generate the longest // bitonic subsequence void printLBS( int arr[], int N)
{ // Store the lengths of LIS
// ending at every index
int lis[N];
// Store the lengths of LDS
// ending at every index
int lds[N];
for ( int i = 0; i < N; i++) {
lis[i] = lds[i] = 1;
}
// Compute LIS for all indices
for ( int i = 0; i < N; i++) {
for ( int j = 0; j < i; j++) {
if (arr[j] < arr[i]) {
if (lis[i] < lis[j] + 1)
lis[i] = lis[j] + 1;
}
}
}
// Compute LDS for all indices
for ( int i = N - 1; i >= 0; i--) {
for ( int j = N - 1; j > i; j--) {
if (arr[j] < arr[i]) {
if (lds[i] < lds[j] + 1)
lds[i] = lds[j] + 1;
}
}
}
// Find the index having
// maximum value of
// lis[i] + lds[i] - 1
int MaxVal = arr[0], inx = 0;
for ( int i = 0; i < N; i++) {
if (MaxVal < lis[i] + lds[i] - 1) {
MaxVal = lis[i] + lds[i] - 1;
inx = i;
}
}
// Stores the count of elements in
// increasing order in Bitonic subsequence
int ct1 = lis[inx];
vector< int > res;
// Store the increasing subsequence
for ( int i = inx; i >= 0 && ct1 > 0; i--) {
if (lis[i] == ct1) {
res.push_back(arr[i]);
ct1--;
}
}
// Sort the bitonic subsequence
// to arrange smaller elements
// at the beginning
reverse(res.begin(), res.end());
// Stores the count of elements in
// decreasing order in Bitonic subsequence
int ct2 = lds[inx] - 1;
for ( int i = inx; i < N && ct2 > 0; i++) {
if (lds[i] == ct2) {
res.push_back(arr[i]);
ct2--;
}
}
// Print the longest
// bitonic sequence
printRes(res);
} // Driver Code int main()
{ int arr[] = { 80, 60, 30, 40, 20, 10 };
int N = sizeof (arr) / sizeof (arr[0]);
printLBS(arr, N);
} |
// Java program to implement // the above approach import java.util.*;
class GFG {
// Function to print the longest // bitonic subsequence static void printRes(Vector<Integer> res)
{ Enumeration enu = res.elements();
while (enu.hasMoreElements())
{
System.out.print(enu.nextElement() + " " );
}
} // Function to generate the longest // bitonic subsequence static void printLBS( int arr[], int N)
{ // Store the lengths of LIS
// ending at every index
int lis[] = new int [N];
// Store the lengths of LDS
// ending at every index
int lds[] = new int [N];
for ( int i = 0 ; i < N; i++)
{
lis[i] = lds[i] = 1 ;
}
// Compute LIS for all indices
for ( int i = 0 ; i < N; i++)
{
for ( int j = 0 ; j < i; j++)
{
if (arr[j] < arr[i])
{
if (lis[i] < lis[j] + 1 )
lis[i] = lis[j] + 1 ;
}
}
}
// Compute LDS for all indices
for ( int i = N - 1 ; i >= 0 ; i--)
{
for ( int j = N - 1 ; j > i; j--)
{
if (arr[j] < arr[i])
{
if (lds[i] < lds[j] + 1 )
lds[i] = lds[j] + 1 ;
}
}
}
// Find the index having
// maximum value of
// lis[i] + lds[i] - 1
int MaxVal = arr[ 0 ], inx = 0 ;
for ( int i = 0 ; i < N; i++)
{
if (MaxVal < lis[i] + lds[i] - 1 )
{
MaxVal = lis[i] + lds[i] - 1 ;
inx = i;
}
}
// Stores the count of elements in
// increasing order in Bitonic subsequence
int ct1 = lis[inx];
Vector<Integer> res = new Vector<Integer>();
// Store the increasing subsequence
for ( int i = inx; i >= 0 && ct1 > 0 ; i--)
{
if (lis[i] == ct1)
{
res.add(arr[i]);
ct1--;
}
}
// Sort the bitonic subsequence
// to arrange smaller elements
// at the beginning
Collections.reverse(res);
// Stores the count of elements in
// decreasing order in Bitonic subsequence
int ct2 = lds[inx] - 1 ;
for ( int i = inx; i < N && ct2 > 0 ; i++)
{
if (lds[i] == ct2)
{
res.add(arr[i]);
ct2--;
}
}
// Print the longest
// bitonic sequence
printRes(res);
} // Driver Code public static void main(String[] args)
{ int arr[] = { 80 , 60 , 30 , 40 , 20 , 10 };
int N = arr.length;
printLBS(arr, N);
} } // This code is contributed by chitranayal |
# Python3 program to implement # the above approach # Function to print the longest # bitonic subsequence def printRes(res):
n = len (res)
for i in range (n):
print (res[i], end = " " )
# Function to generate the longest # bitonic subsequence def printLBS(arr, N):
# Store the lengths of LIS
# ending at every index
lis = [ 0 ] * N
# Store the lengths of LDS
# ending at every index
lds = [ 0 ] * N
for i in range (N):
lis[i] = lds[i] = 1
# Compute LIS for all indices
for i in range (N):
for j in range (i):
if arr[j] < arr[i]:
if lis[i] < lis[j] + 1 :
lis[i] = lis[j] + 1
# Compute LDS for all indices
for i in range (N - 1 , - 1 , - 1 ):
for j in range (N - 1 , i, - 1 ):
if arr[j] < arr[i]:
if lds[i] < lds[j] + 1 :
lds[i] = lds[j] + 1
# Find the index having
# maximum value of
# lis[i]+lds[i]+1
MaxVal = arr[ 0 ]
inx = 0
for i in range (N):
if MaxVal < lis[i] + lds[i] - 1 :
MaxVal = lis[i] + lds[i] - 1
inx = i
# Stores the count of elements in
# increasing order in Bitonic subsequence
ct1 = lis[inx]
res = []
i = inx
# Store the increasing subsequence
while i > = 0 and ct1 > 0 :
if lis[i] = = ct1:
res.append(arr[i])
ct1 - = 1
i - = 1
# Sort the bitonic subsequence
# to arrange smaller elements
# at the beginning
res.reverse()
# Stores the count of elements in
# decreasing order in Bitonic subsequence
ct2 = lds[inx] - 1
i = inx
while i < N and ct2 > 0 :
if lds[i] = = ct2:
res.append(arr[i])
ct2 - = 1
i + = 1
# Print the longest
# bitonic sequence
printRes(res)
# Driver code arr = [ 80 , 60 , 30 , 40 , 20 , 10 ]
N = len (arr)
printLBS(arr, N) # This code is contributed by Stuti Pathak |
// C# program to implement // the above approach using System;
using System.Collections.Generic;
class GFG{
// Function to print the longest
// bitonic subsequence
static void printRes(List< int > res)
{
foreach ( int enu in res)
{
Console.Write(enu + " " );
}
}
// Function to generate the longest
// bitonic subsequence
static void printLBS( int [] arr, int N)
{
// Store the lengths of LIS
// ending at every index
int [] lis = new int [N];
// Store the lengths of LDS
// ending at every index
int [] lds = new int [N];
for ( int i = 0; i < N; i++)
{
lis[i] = lds[i] = 1;
}
// Compute LIS for all indices
for ( int i = 0; i < N; i++)
{
for ( int j = 0; j < i; j++)
{
if (arr[j] < arr[i])
{
if (lis[i] < lis[j] + 1)
lis[i] = lis[j] + 1;
}
}
}
// Compute LDS for all indices
for ( int i = N - 1; i >= 0; i--)
{
for ( int j = N - 1; j > i; j--)
{
if (arr[j] < arr[i])
{
if (lds[i] < lds[j] + 1)
lds[i] = lds[j] + 1;
}
}
}
// Find the index having
// maximum value of
// lis[i] + lds[i] - 1
int MaxVal = arr[0], inx = 0;
for ( int i = 0; i < N; i++)
{
if (MaxVal < lis[i] + lds[i] - 1)
{
MaxVal = lis[i] + lds[i] - 1;
inx = i;
}
}
// Stores the count of elements in
// increasing order in Bitonic subsequence
int ct1 = lis[inx];
List< int > res = new List< int >();
// Store the increasing subsequence
for ( int i = inx; i >= 0 && ct1 > 0; i--)
{
if (lis[i] == ct1)
{
res.Add(arr[i]);
ct1--;
}
}
// Sort the bitonic subsequence
// to arrange smaller elements
// at the beginning
res.Reverse();
// Stores the count of elements in
// decreasing order in Bitonic subsequence
int ct2 = lds[inx] - 1;
for ( int i = inx; i < N && ct2 > 0; i++)
{
if (lds[i] == ct2)
{
res.Add(arr[i]);
ct2--;
}
}
// Print the longest
// bitonic sequence
printRes(res);
}
// Driver Code
public static void Main(String[] args)
{
int [] arr = {80, 60, 30, 40, 20, 10};
int N = arr.Length;
printLBS(arr, N);
}
} // This code is contributed by Amit Katiyar |
<script> // JavaScript Program to implement // the above approach // Function to print the longest // bitonic subsequence function printRes( res)
{ var n = res.length;
for ( var i = 0; i < n; i++) {
document.write( res[i] + " " );
}
} // Function to generate the longest // bitonic subsequence function printLBS(arr, N)
{ // Store the lengths of LIS
// ending at every index
var lis = Array(N);
// Store the lengths of LDS
// ending at every index
var lds = Array(N);
for ( var i = 0; i < N; i++) {
lis[i] = lds[i] = 1;
}
// Compute LIS for all indices
for ( var i = 0; i < N; i++) {
for ( var j = 0; j < i; j++) {
if (arr[j] < arr[i]) {
if (lis[i] < lis[j] + 1)
lis[i] = lis[j] + 1;
}
}
}
// Compute LDS for all indices
for ( var i = N - 1; i >= 0; i--) {
for ( var j = N - 1; j > i; j--) {
if (arr[j] < arr[i]) {
if (lds[i] < lds[j] + 1)
lds[i] = lds[j] + 1;
}
}
}
// Find the index having
// maximum value of
// lis[i] + lds[i] - 1
var MaxVal = arr[0], inx = 0;
for ( var i = 0; i < N; i++) {
if (MaxVal < lis[i] + lds[i] - 1) {
MaxVal = lis[i] + lds[i] - 1;
inx = i;
}
}
// Stores the count of elements in
// increasing order in Bitonic subsequence
var ct1 = lis[inx];
var res = [];
// Store the increasing subsequence
for ( var i = inx; i >= 0 && ct1 > 0; i--) {
if (lis[i] == ct1) {
res.push(arr[i]);
ct1--;
}
}
// Sort the bitonic subsequence
// to arrange smaller elements
// at the beginning
res.reverse();
// Stores the count of elements in
// decreasing order in Bitonic subsequence
var ct2 = lds[inx] - 1;
for ( var i = inx; i < N && ct2 > 0; i++) {
if (lds[i] == ct2) {
res.push(arr[i]);
ct2--;
}
}
// Print the longest
// bitonic sequence
printRes(res);
} // Driver Code var arr = [80, 60, 30, 40, 20, 10];
var N = arr.length;
printLBS(arr, N); </script> |
80 60 30 20 10
Time Complexity: O(N2)
Auxiliary Space: O(N)