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++
// 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
// 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
# 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#
// 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 |
Javascript
<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)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!