Longest Bitonic Subsequence (original) (raw)

Last Updated : 07 Mar, 2025

Try it on GfG Practice redirect icon

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 decreasing sequence should not be considered as a bitonic sequence.

**Examples:

**Input: arr[]= [12, 11, 40, 5, 3, 1]
**Output: 5
**Explanation: The Longest Bitonic Subsequence is {12, 40, 5, 3, 1} which is of length 5.

**Input: arr[] = [80, 60, 30]
**Output: 0
**Explanation: There is no possible Bitonic Subsequence.

Table of Content

Using Recursion - O(n*(2^n)) Time and O(n) Space

The **recursive approach for finding the longest bitonic subsequence relies on breaking the problem into two parts for each potential peak:

At each step, the algorithm explores two choices:

**Recurrence Relation:

For any index i, the solution involves:

**Base Cases:

C++ `

// C++ implementation to find longest Bitonic // subsequence using Recursion #include <bits/stdc++.h> using namespace std;

// Function to find the longest decreasing subsequence // to the left int left(int prev, int idx, vector& arr) { if (idx < 0) { return 0; }

// Check if nums[idx] can be included 
// in decreasing subsequence
int include = 0;
if (arr[idx] < arr[prev]) {
    include = 1 + left(idx, idx - 1, arr);
}

// Return the maximum of including 
// or excluding nums[idx]
return max(include, left(prev, idx - 1, arr));

}

// Function to find the longest decreasing // subsequence to the right int right(int prev, int idx, vector& arr) { if (idx >= arr.size()) { return 0; }

// Check if nums[idx] can be included 
// in decreasing subsequence
int include = 0;
if (arr[idx] < arr[prev]) {
    include = 1 + right(idx, idx + 1, arr);
}

// Return the maximum of including or 
// excluding nums[idx]
return max(include, right(prev, idx + 1, arr));

}

// Function to find the longest bitonic sequence int LongestBitonicSequence(vector& arr) { int maxLength = 0;

// Iterate over potential peaks in the array
for (int i = 1; i < arr.size() - 1; i++) {
  
    // Find the longest decreasing subsequences 
    // on both sides of arr[i]
    int leftLen = left(i, i - 1, arr);
    int rightLen = right(i, i + 1, arr);

    // Ensure both left and right subsequences are valid
    if (leftLen == 0 || rightLen == 0) {
        leftLen = 0;
        rightLen = 0;
    }

    // Update maximum bitonic sequence length
    maxLength = max(maxLength, leftLen + rightLen + 1);
}

// If no valid bitonic sequence, return 0
return (maxLength < 3) ? 0 : maxLength;

}

int main() {

vector<int> arr = {12, 11, 40, 5, 3, 1};

cout << LongestBitonicSequence(arr) << endl;

return 0;

}

Java

// Java implementation to find longest Bitonic // subsequence using Recursion import java.util.ArrayList; import java.util.*;

class GfG {

// Function to find the longest decreasing subsequence 
// to the left
static int left(int prev, int idx, ArrayList<Integer> arr) {
    if (idx < 0) {
        return 0;
    }

    // Check if nums[idx] can be included 
    // in decreasing subsequence
    int include = 0;
    if (arr.get(idx) < arr.get(prev)) {
        include = 1 + left(idx, idx - 1, arr);
    }

    // Return the maximum of including 
    // or excluding nums[idx]
    return Math.max(include, left(prev, idx - 1, arr));
}

// Function to find the longest decreasing 
// subsequence to the right
static int right(int prev, int idx, ArrayList<Integer> arr) {
    if (idx >= arr.size()) {
        return 0;
    }

    // Check if nums[idx] can be included 
    // in decreasing subsequence
    int include = 0;
    if (arr.get(idx) < arr.get(prev)) {
        include = 1 + right(idx, idx + 1, arr);
    }

    // Return the maximum of including or 
    // excluding nums[idx]
    return Math.max(include, right(prev, idx + 1, arr));
}

// Function to find the longest bitonic sequence
static int LongestBitonicSequence(ArrayList<Integer> arr) {
    int maxLength = 0;

    // Iterate over potential peaks in the array
    for (int i = 1; i < arr.size() - 1; i++) {

        // Find the longest decreasing subsequences 
        // on both sides of nums[i]
        int leftLen = left(i, i - 1, arr);
        int rightLen = right(i, i + 1, arr);

        // Ensure both left and right subsequences are valid
        if (leftLen == 0 || rightLen == 0) {
            leftLen = 0;
            rightLen = 0;
        }

        // Update maximum bitonic sequence length
        maxLength = Math.max(maxLength, leftLen + rightLen + 1);
    }

    // If no valid bitonic sequence, return 0
    return (maxLength < 3) ? 0 : maxLength;
}

public static void main(String[] args) {
  
    ArrayList<Integer> arr 
       = new ArrayList<>(Arrays.asList(12, 11, 40, 5, 3, 1));
    System.out.println(LongestBitonicSequence(arr));
}

}

Python

Python implementation to find longest Bitonic

subsequence using Recursion

Function to find the longest decreasing

subsequence to the left

def left(prev, idx, arr): if idx < 0: return 0

# Check if arr[idx] can be included in the 
# decreasing subsequence
include = 0
if arr[idx] < arr[prev]:
    include = 1 + left(idx, idx - 1, arr)

# Return the maximum of including or excluding arr[idx]
return max(include, left(prev, idx - 1, arr))

Function to find the longest decreasing subsequence

to the right

def right(prev, idx, arr): if idx >= len(arr): return 0

# Check if nums[idx] can be included in the 
# decreasing subsequence
include = 0
if arr[idx] < arr[prev]:
    include = 1 + right(idx, idx + 1, arr)

# Return the maximum of including or excluding arr[idx]
return max(include, right(prev, idx + 1, arr))

Function to find the longest bitonic sequence

def LongestBitonicSequence(arr): max_length = 0

# Iterate over potential peaks in the array
for i in range(1, len(arr) - 1):

    # Find the longest decreasing subsequences 
    # on both sides of arr[i]
    left_len = left(i, i - 1, arr)
    right_len = right(i, i + 1, arr)

    # Ensure both left and right subsequences are valid
    if left_len == 0 or right_len == 0:
        left_len = 0
        right_len = 0

    # Update maximum bitonic sequence length
    max_length = max(max_length, left_len + right_len + 1)

# If no valid bitonic sequence, return 0
return 0 if max_length < 3 else max_length

if name == "main":

arr = [12, 11, 40, 5, 3, 1]
print(LongestBitonicSequence(arr))

C#

// C# implementation to find longest Bitonic // subsequence using Recursion using System; using System.Collections.Generic;

class GfG {

// Function to find the longest decreasing 
// subsequence to the left
static int Left(int prev, int idx, List<int> arr) {
    if (idx < 0) {
        return 0;
    }

    // Check if nums[idx] can be included in
    // decreasing subsequence
    int include = 0;
    if (arr[idx] < arr[prev]) {
        include = 1 + Left(idx, idx - 1, arr);
    }

    // Return the maximum of including or excluding nums[idx]
    return Math.Max(include, Left(prev, idx - 1, arr));
}

// Function to find the longest decreasing 
// subsequence to the right
static int Right(int prev, int idx, List<int> arr) {
    if (idx >= arr.Count) {
        return 0;
    }

    // Check if nums[idx] can be included
    // in decreasing subsequence
    int include = 0;
    if (arr[idx] < arr[prev]) {
        include = 1 + Right(idx, idx + 1, arr);
    }

    // Return the maximum of including or excluding nums[idx]
    return Math.Max(include, Right(prev, idx + 1, arr));
}

// Function to find the longest bitonic sequence
static int LongestBitonicSequence(List<int> arr) {
    int maxLength = 0;

    // Iterate over potential peaks in the array
    for (int i = 1; i < arr.Count - 1; i++) {
      
        // Find the longest decreasing subsequences
        // on both sides of nums[i]
        int leftLen = Left(i, i - 1, arr);
        int rightLen = Right(i, i + 1, arr);

        // Ensure both left and right subsequences are valid
        if (leftLen == 0 || rightLen == 0) {
            leftLen = 0;
            rightLen = 0;
        }

        // Update maximum bitonic sequence length
        maxLength = Math.Max(maxLength, 
                             leftLen + rightLen + 1);
    }

    // If no valid bitonic sequence, return 0
    return (maxLength < 3) ? 0 : maxLength;
}

static void Main() {

    List<int> arr 
       = new List<int> { 12, 11, 40, 5, 3, 1 };

    Console.WriteLine(LongestBitonicSequence(arr));
}

}

JavaScript

// Javascript implementation to find longest Bitonic // subsequence using Recursion