Longest Bitonic Subsequence | DP-15

12 Jan, 2022
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 argument and returns the length of the longest bitonic subsequence. A sequence, sorted in increasing order is considered Bitonic with the decreasing part as empty. Similarly, decreasing order sequence is considered Bitonic with the increasing part as empty. Examples:
Input arr[] = {1, 11, 2, 10, 4, 5, 2, 1};
Output: 6 (A Longest Bitonic Subsequence of length 6 is 1, 2, 10, 4, 2, 1)

Input arr[] = {12, 11, 40, 5, 3, 1}
Output: 5 (A Longest Bitonic Subsequence of length 5 is 12, 11, 5, 3, 1)

Input arr[] = {80, 60, 30, 40, 20, 10}
Output: 5 (A Longest Bitonic Subsequence of length 5 is 80, 60, 30, 20, 10)
Source: Microsoft Interview Question 
Solution This problem is a variation of standard Longest Increasing Subsequence (LIS) problem. Let the input array be arr[] of length n. We need to construct two arrays lis[] and lds[] using Dynamic Programming solution of LIS problem. lis[i] stores the length of the Longest Increasing subsequence ending with arr[i]. lds[i] stores the length of the longest Decreasing subsequence starting from arr[i]. Finally, we need to return the max value of lis[i] + lds[i] – 1 where i is from 0 to n-1.Following is the implementation of the above Dynamic Programming solution.  
C++
Java
Python3
C#
PHP
Javascript
/* Dynamic Programming implementation of longest bitonic subsequence problem */#include<stdio.h>#include<stdlib.h> /* lbs() returns the length of the Longest Bitonic Subsequence in    arr[] of size n. The function mainly creates two temporary arrays    lis[] and lds[] and returns the maximum lis[i] + lds[i] - 1.     lis[i] ==> Longest Increasing subsequence ending with arr[i]    lds[i] ==> Longest decreasing subsequence starting with arr[i]*/int lbs( int arr[], int n ){   int i, j;    /* Allocate memory for LIS[] and initialize LIS values as 1 for      all indexes */   int *lis = new int[n];   for (i = 0; i < n; i++)      lis[i] = 1;    /* Compute LIS values from left to right */   for (i = 1; i < n; i++)      for (j = 0; j < i; j++)         if (arr[i] > arr[j] && lis[i] < lis[j] + 1)            lis[i] = lis[j] + 1;    /* Allocate memory for lds and initialize LDS values for      all indexes */   int *lds = new int [n];   for (i = 0; i < n; i++)      lds[i] = 1;    /* Compute LDS values from right to left */   for (i = n-2; i >= 0; i--)      for (j = n-1; j > i; j--)         if (arr[i] > arr[j] && lds[i] < lds[j] + 1)            lds[i] = lds[j] + 1;     /* Return the maximum value of lis[i] + lds[i] - 1*/   int max = lis[0] + lds[0] - 1;   for (i = 1; i < n; i++)     if (lis[i] + lds[i] - 1 > max)         max = lis[i] + lds[i] - 1;   return max;} /* Driver program to test above function */int main(){  int arr[] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5,              13, 3, 11, 7, 15};  int n = sizeof(arr)/sizeof(arr[0]);  printf("Length of LBS is %d\n", lbs( arr, n ) );  return 0;}
/* Dynamic Programming implementation in Java for longest bitonic   subsequence problem */import java.util.*;import java.lang.*;import java.io.*; class LBS{    /* lbs() returns the length of the Longest Bitonic Subsequence in    arr[] of size n. The function mainly creates two temporary arrays    lis[] and lds[] and returns the maximum lis[i] + lds[i] - 1.     lis[i] ==> Longest Increasing subsequence ending with arr[i]    lds[i] ==> Longest decreasing subsequence starting with arr[i]    */    static int lbs( int arr[], int n )    {        int i, j;         /* Allocate memory for LIS[] and initialize LIS values as 1 for            all indexes */        int[] lis = new int[n];        for (i = 0; i < n; i++)            lis[i] = 1;         /* Compute LIS values from left to right */        for (i = 1; i < n; i++)            for (j = 0; j < i; j++)                if (arr[i] > arr[j] && lis[i] < lis[j] + 1)                    lis[i] = lis[j] + 1;         /* Allocate memory for lds and initialize LDS values for            all indexes */        int[] lds = new int [n];        for (i = 0; i < n; i++)            lds[i] = 1;         /* Compute LDS values from right to left */        for (i = n-2; i >= 0; i--)            for (j = n-1; j > i; j--)                if (arr[i] > arr[j] && lds[i] < lds[j] + 1)                    lds[i] = lds[j] + 1;          /* Return the maximum value of lis[i] + lds[i] - 1*/        int max = lis[0] + lds[0] - 1;        for (i = 1; i < n; i++)            if (lis[i] + lds[i] - 1 > max)                max = lis[i] + lds[i] - 1;         return max;    }     public static void main (String[] args)    {        int arr[] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5,                    13, 3, 11, 7, 15};        int n = arr.length;        System.out.println("Length of LBS is "+ lbs( arr, n ));    }}
# Dynamic Programming implementation of longest bitonic subsequence problem"""lbs() returns the length of the Longest Bitonic Subsequence inarr[] of size n. The function mainly creates two temporary arrayslis[] and lds[] and returns the maximum lis[i] + lds[i] - 1. lis[i] ==> Longest Increasing subsequence ending with arr[i]lds[i] ==> Longest decreasing subsequence starting with arr[i]""" def lbs(arr):    n = len(arr)      # allocate memory for LIS[] and initialize LIS values as 1    # for all indexes    lis = [1 for i in range(n+1)]     # Compute LIS values from left to right    for i in range(1 , n):        for j in range(0 , i):            if ((arr[i] > arr[j]) and (lis[i] < lis[j] +1)):                lis[i] = lis[j] + 1     # allocate memory for LDS and initialize LDS values for    # all indexes    lds = [1 for i in range(n+1)]         # Compute LDS values from right to left    for i in reversed(range(n-1)): #loop from n-2 downto 0        for j in reversed(range(i-1 ,n)): #loop from n-1 downto i-1            if(arr[i] > arr[j] and lds[i] < lds[j] + 1):                lds[i] = lds[j] + 1      # Return the maximum value of (lis[i] + lds[i] - 1)    maximum = lis[0] + lds[0] - 1    for i in range(1 , n):        maximum = max((lis[i] + lds[i]-1), maximum)         return maximum # Driver program to test the above functionarr =  [0 , 8 , 4, 12, 2, 10 , 6 , 14 , 1 , 9 , 5 , 13,        3, 11 , 7 , 15]print ("Length of LBS is",lbs(arr)) # This code is contributed by Nikhil Kumar Singh(nickzuck_007)
/* Dynamic Programming implementation in   C# for longest bitonic subsequence problem */using System; class LBS {         /* lbs() returns the length of the Longest Bitonic Subsequence in    arr[] of size n. The function mainly creates two temporary arrays    lis[] and lds[] and returns the maximum lis[i] + lds[i] - 1.     lis[i] ==> Longest Increasing subsequence ending with arr[i]    lds[i] ==> Longest decreasing subsequence starting with arr[i]    */    static int lbs(int[] arr, int n)    {        int i, j;         /* Allocate memory for LIS[] and initialize           LIS values as 1 for all indexes */        int[] lis = new int[n];        for (i = 0; i < n; i++)            lis[i] = 1;         /* Compute LIS values from left to right */        for (i = 1; i < n; i++)            for (j = 0; j < i; j++)                if (arr[i] > arr[j] && lis[i] < lis[j] + 1)                    lis[i] = lis[j] + 1;         /* Allocate memory for lds and initialize LDS values for            all indexes */        int[] lds = new int[n];        for (i = 0; i < n; i++)            lds[i] = 1;         /* Compute LDS values from right to left */        for (i = n - 2; i >= 0; i--)            for (j = n - 1; j > i; j--)                if (arr[i] > arr[j] && lds[i] < lds[j] + 1)                    lds[i] = lds[j] + 1;         /* Return the maximum value of lis[i] + lds[i] - 1*/        int max = lis[0] + lds[0] - 1;        for (i = 1; i < n; i++)            if (lis[i] + lds[i] - 1 > max)                max = lis[i] + lds[i] - 1;         return max;    }         // Driver code    public static void Main()    {        int[] arr = { 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5,                                      13, 3, 11, 7, 15 };        int n = arr.Length;        Console.WriteLine("Length of LBS is " + lbs(arr, n));    }} // This code is contributed by vt_m.
<?php// Dynamic Programming implementation// of longest bitonic subsequence problem /* lbs() returns the length of the Longest   Bitonic Subsequence in arr[] of size n.   The function mainly creates two temporary   arrays lis[] and lds[] and returns the   maximum lis[i] + lds[i] - 1.    lis[i] ==> Longest Increasing subsequence              ending with arr[i]   lds[i] ==> Longest decreasing subsequence              starting with arr[i]*/function lbs(&$arr, $n){     /* Allocate memory for LIS[] and initialize       LIS values as 1 for all indexes */    $lis = array_fill(0, $n, NULL);    for ($i = 0; $i < $n; $i++)        $lis[$i] = 1;         /* Compute LIS values from left to right */    for ($i = 1; $i < $n; $i++)        for ($j = 0; $j < $i; $j++)            if ($arr[$i] > $arr[$j] &&                $lis[$i] < $lis[$j] + 1)                $lis[$i] = $lis[$j] + 1;         /* Allocate memory for lds and initialize       LDS values for all indexes */    $lds = array_fill(0, $n, NULL);    for ($i = 0; $i < $n; $i++)        $lds[$i] = 1;         /* Compute LDS values from right to left */    for ($i = $n - 2; $i >= 0; $i--)        for ($j = $n - 1; $j > $i; $j--)            if ($arr[$i] > $arr[$j] &&                $lds[$i] < $lds[$j] + 1)                $lds[$i] = $lds[$j] + 1;         /* Return the maximum value of       lis[i] + lds[i] - 1*/    $max = $lis[0] + $lds[0] - 1;    for ($i = 1; $i < $n; $i++)        if ($lis[$i] + $lds[$i] - 1 > $max)            $max = $lis[$i] + $lds[$i] - 1;    return $max;} // Driver Code$arr = array(0, 8, 4, 12, 2, 10, 6, 14,             1, 9, 5, 13, 3, 11, 7, 15);$n = sizeof($arr);echo "Length of LBS is " . lbs( $arr, $n ); // This code is contributed by ita_c?>
<script> /* Dynamic Programming implementation in JavaScript for longest bitonic   subsequence problem */            /* lbs() returns the length of the Longest Bitonic Subsequence in    arr[] of size n. The function mainly creates two temporary arrays    lis[] and lds[] and returns the maximum lis[i] + lds[i] - 1.       lis[i] ==> Longest Increasing subsequence ending with arr[i]    lds[i] ==> Longest decreasing subsequence starting with arr[i]    */    function lbs(arr,n)    {        let i, j;        /* Allocate memory for LIS[] and initialize LIS values as 1 for            all indexes */        let lis = new Array(n)        for (i = 0; i < n; i++)            lis[i] = 1;                 /* Compute LIS values from left to right */        for (i = 1; i < n; i++)            for (j = 0; j < i; j++)                if (arr[i] > arr[j] && lis[i] < lis[j] + 1)                    lis[i] = lis[j] + 1;           /* Allocate memory for lds and initialize LDS values for            all indexes */        let lds = new Array(n);        for (i = 0; i < n; i++)            lds[i] = 1;           /* Compute LDS values from right to left */        for (i = n-2; i >= 0; i--)            for (j = n-1; j > i; j--)                if (arr[i] > arr[j] && lds[i] < lds[j] + 1)                    lds[i] = lds[j] + 1;              /* Return the maximum value of lis[i] + lds[i] - 1*/        let max = lis[0] + lds[0] - 1;        for (i = 1; i < n; i++)            if (lis[i] + lds[i] - 1 > max)                max = lis[i] + lds[i] - 1;           return max;    }    let arr=[0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]    let n = arr.length;    document.write("Length of LBS is "+ lbs( arr, n ));             // This code is contributed by avanitrachhadiya2155     </script>
Output: 
Chapters
descriptions off, selected
captions settings, opens captions settings dialog
captions off, selected
English
default, selected
This is a modal window.
Beginning of dialog window. Escape will cancel and close the window.
End of dialog window.
 Length of LBS is 7
Time Complexity: O(n^2) Auxiliary Space: O(n) 
Longest Bitonic Subsequence (Visualisation) | Dynamic Programming | Set 15 | GeeksforGeeks - YouTubeGeeksforGeeks530K subscribersLongest Bitonic Subsequence (Visualisation) | Dynamic Programming | Set 15 | GeeksforGeeksWatch laterShareCopy linkInfoShoppingTap to unmuteIf playback doesn't begin shortly, try restarting your device.You're signed outVideos you watch may be added to the TV's watch history and influence TV recommendations. To avoid this, cancel and sign in to YouTube on your computer.CancelConfirmMore videosMore videosSwitch cameraShareInclude playlistAn error occurred while retrieving sharing information. Please try again later.Watch on0:000:000:00 / 3:36•Live•<div class="player-unavailable"><h1 class="message">An error occurred.</h1><div class="submessage"><a href="https://www.youtube.com/watch?v=CxpfBdPaRTE" target="_blank">Try watching this video on www.youtube.com</a>, or enable JavaScript if it is disabled in your browser.</div></div>
 
Longest Bitonic Subsequence (Explanation) | Dynamic Programming | Set 15 | GeeksforGeeks - YouTubeGeeksforGeeks530K subscribersLongest Bitonic Subsequence (Explanation) | Dynamic Programming | Set 15 | GeeksforGeeksWatch laterShareCopy linkInfoShoppingTap to unmuteIf playback doesn't begin shortly, try restarting your device.You're signed outVideos you watch may be added to the TV's watch history and influence TV recommendations. To avoid this, cancel and sign in to YouTube on your computer.CancelConfirmMore videosMore videosSwitch cameraShareInclude playlistAn error occurred while retrieving sharing information. Please try again later.Watch on0:000:000:00 / 6:04•Live•<div class="player-unavailable"><h1 class="message">An error occurred.</h1><div class="submessage"><a href="https://www.youtube.com/watch?v=CZ8eM2f3_gY" target="_blank">Try watching this video on www.youtube.com</a>, or enable JavaScript if it is disabled in your browser.</div></div>
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above 
ukasp
avanitrachhadiya2155
amartyaghoshgfg
LIS
Microsoft
subsequence
Dynamic Programming
Microsoft
Dynamic Programming
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Subset Sum Problem | DP-25
Longest Palindromic Substring | Set 1
Floyd Warshall Algorithm | DP-16
Coin Change | DP-7
Matrix Chain Multiplication | DP-8
Sieve of Eratosthenes
Bellman–Ford Algorithm | DP-23
Travelling Salesman Problem | Set 1 (Naive and Dynamic Programming)
Minimum number of jumps to reach end
Find if there is a path between two vertices in an undirected graph