Open In App

Print Longest Bitonic subsequence (Space Optimized Approach)

Improve
Improve
Like Article
Like
Save
Share
Report

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.

  1. 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.
  2. Once computed, find the ith index which contains the maximum value of lis[i] + lds[i] – 1
  3. Create res[] to store all the elements of the longest bitonic sequence in decreasing order of elements followed by increasing order of elements.
  4. 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>


Output: 

80 60 30 20 10

 

Time Complexity: O(N2
Auxiliary Space: O(N) 



Last Updated : 14 Jun, 2021
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads