VOOZH about

URL: https://www.geeksforgeeks.org/dsa/longest-bitonic-subsequence-dp-15/

⇱ Longest Bitonic Subsequence - GeeksforGeeks


  • Courses
  • Tutorials
  • Interview Prep

Longest Bitonic Subsequence

Last Updated : 28 Apr, 2026

Given an array arr[] containing n positive integers, find the length of the longest bitonic subsequence. A subsequence of numbers is called bitonic if it is first strictly increasing, then strictly decreasing.
Note: Only strictly increasing (no decreasing part) or a strictly decreasing sequence should not be considered as a bitonic sequence.

Examples:

Input: n = 5, nums[] = [1, 2, 5, 3, 2]
Output: 5
Explanation: The sequence [1, 2, 5] is increasing and the sequence [3, 2] is decreasing so merging both we will get length 5.

Input: n = 8, nums[] = [1, 11, 2, 10, 4, 5, 2, 1]
Output: 6
Explanation: The bitonic sequence [1, 2, 10, 4, 2, 1] has length 6.

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

In this approach, we consider every element of the array as a possible peak of a bitonic subsequence.
For an element to be a valid peak:

  • The elements on its left must form a strictly increasing subsequence.
  • The elements on its right must form a strictly decreasing subsequence.

A sequence that is only increasing or only decreasing does not qualify as bitonic, because a bitonic subsequence must have both parts with a clear turning point (the peak).

So, for each index i, we calculate:

  • the longest increasing subsequence ending at i (from the left), and
  • the longest decreasing subsequence starting from i (to the right).

This gives us the bitonic subsequence length with i as the peak.

Finally, we take the maximum bitonic length among all choices of peaks.


Output
5

Using Top-Down DP (Memoization) - O(n^2) Time and O(n^2) Space

We treat every element as a potential peak of a bitonic sequence. For each peak, we recursively find the longest decreasing subsequence on the left and right sides using memoization to avoid recomputation. At each step, we decide whether to include the current element based on the decreasing condition. If both left and right parts exist, we combine their lengths with the peak (left + right + 1). Finally, we return the maximum length among all such valid peaks.

Algorithm:

  • We consider each element as a peak and try to form a bitonic sequence around it.
  • Using recursion + memoization, we find the longest decreasing subsequence on the left and right of the peak.
  • At each step, we either include or skip an element based on comparison.
  • If both sides exist, we compute length as left + right + 1.
  • Return the maximum length among all peaks.

Output
5

Using Bottom-Up DP (Tabulation) - O(n^2) Time and O(n) Space

We compute the LIS from left to right and the LDS from right to left. For each index i, LIS is formed by extending previous smaller elements (j < i), while LDS is formed by extending smaller elements on the right (j > i). Then, treating each index as a peak, the bitonic length is calculated as LIS[i] + LDS[i] - 1. We consider only those indices where both LIS[i] > 1 and LDS[i] > 1, and return the maximum value among them.

Algorithm:

  • First, we check if the array size is less than 3, since a bitonic sequence requires at least 3 elements.
  • We compute leftLIS[], where each index stores the longest increasing subsequence ending at that position.
  • We compute rightLDS[], where each index stores the longest decreasing subsequence starting from that position.
  • Then, we treat every index as a peak and combine LIS + LDS - 1 to get the bitonic length.
  • Finally, we return the maximum valid length where both increasing and decreasing parts exist.

Output
5
Comment