Print Longest Bitonic subsequence (Space Optimized Approach)
Last Updated :
14 Jun, 2021
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>
Time Complexity: O(N2)
Auxiliary Space: O(N)
Similar Reads
Printing Longest Bitonic Subsequence The Longest Bitonic Subsequence problem is to find the longest subsequence of a given sequence such that it is first increasing and then decreasing. A sequence, sorted in increasing order is considered Bitonic with the decreasing part as empty. Similarly, decreasing order sequence is considered Bito
12 min read
Length of longest strict bitonic subsequence 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 be
15+ min read
Longest Bitonic Subsequence Given an array arr[] containing n positive integers, a subsequence of numbers is called bitonic if it is first strictly increasing, then strictly decreasing. The task is to find the length of the longest bitonic subsequence. Note: Only strictly increasing (no decreasing part) or a strictly decreasin
15+ min read
Longest Reverse Bitonic Sequence Given an arr[] of length N, the task is to find the length of longest Reverse Bitonic Subsequence. A subsequence is called Reverse Bitonic if it is first decreasing, then increasing.Examples: Input: arr[] = {10, 11, 2, 1, 1, 5, 2, 4} Output: 5Explanation: The longest subsequence which first decrease
9 min read
Longest Bitonic Subsequence in O(n log n) Given an array arr[0 ⦠n-1] containing n positive integers, a subsequence of arr[] is called Bitonic if it is first increasing, then decreasing. Write a function that takes an array as an argument and returns the length of the longest bitonic subsequence. A sequence, sorted in increasing order is co
15+ min read