Friday, January 10, 2025
Google search engine
HomeData Modelling & AIPrint Longest Bitonic subsequence (Space Optimized Approach)

Print Longest Bitonic subsequence (Space Optimized Approach)

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) 

Feeling lost in the world of random DSA topics, wasting time without progress? It’s time for a change! Join our DSA course, where we’ll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

RELATED ARTICLES

Most Popular

Recent Comments