Find longest bitonic sequence such that increasing and decreasing parts are from two different arrays in Python

A bitonic sequence is a sequence that first increases and then decreases. In this problem, we need to find the longest bitonic sequence where the increasing part comes from the first array and the decreasing part comes from the second array, both as subsequences.

Given two arrays A and B, we find the longest increasing subsequence from A, then the longest increasing subsequence from the reverse of B (which gives us a decreasing sequence), and combine them.

Algorithm Overview

The solution uses dynamic programming with binary search optimization:

  • Find the longest increasing subsequence (LIS) from array A
  • Reverse array B and find its LIS (which becomes decreasing when reversed back)
  • Combine both parts to form the bitonic sequence

Implementation

def index_ceiling(arr, T, left, right, key):
    """Binary search to find ceiling index"""
    while right - left > 1:
        mid = left + (right - left) // 2
        if arr[T[mid]] >= key:
            right = mid
        else:
            left = mid
    return right

def long_inc_seq(A, result):
    """Find longest increasing subsequence using binary search optimization"""
    n = len(A)
    if n == 0:
        return
    
    tails_idx = [0] * n  # indices of tails of increasing subsequences
    prev_idx = [-1] * n  # previous element indices for reconstruction
    length = 1
    
    for i in range(1, n):
        if A[i] < A[tails_idx[0]]:
            # New smallest element
            tails_idx[0] = i
        elif A[i] > A[tails_idx[length - 1]]:
            # Extend the longest subsequence
            prev_idx[i] = tails_idx[length - 1]
            tails_idx[length] = i
            length += 1
        else:
            # Replace an element in existing subsequence
            pos = index_ceiling(A, tails_idx, -1, length - 1, A[i])
            prev_idx[i] = tails_idx[pos - 1]
            tails_idx[pos] = i
    
    # Reconstruct the subsequence
    i = tails_idx[length - 1]
    while i >= 0:
        result.append(A[i])
        i = prev_idx[i]

def find_longest_bitonic(A, B):
    """Find longest bitonic sequence from two arrays"""
    result = []
    
    # Get longest increasing subsequence from A
    long_inc_seq(A, result)
    result.reverse()  # Reverse to get correct order
    
    # Get longest increasing subsequence from reversed B
    # (which gives decreasing sequence when we don't reverse the result)
    B_reversed = B[::-1]
    long_inc_seq(B_reversed, result)
    
    return result

# Example usage
A = [2, 6, 3, 5, 4, 6]
B = [9, 7, 5, 8, 4, 3]

bitonic_sequence = find_longest_bitonic(A, B)
print("Longest bitonic sequence:", bitonic_sequence)
Longest bitonic sequence: [2, 3, 4, 6, 9, 7, 5, 4, 3]

How It Works

The algorithm works in three main steps:

  1. Find LIS from A: Uses binary search to efficiently find the longest increasing subsequence from array A, which forms the increasing part of our bitonic sequence
  2. Find LIS from reversed B: Reverses array B and finds its LIS. When we don't reverse this result, it gives us a decreasing sequence
  3. Combine results: The two parts are combined to form the complete bitonic sequence

Example Walkthrough

For A = [2, 6, 3, 5, 4, 6] and B = [9, 7, 5, 8, 4, 3]:

  • LIS from A: [2, 3, 4, 6] (increasing part)
  • B reversed: [3, 4, 8, 5, 7, 9]
  • LIS from reversed B: [3, 4, 5, 7, 9] ? becomes [9, 7, 5, 4, 3] (decreasing part)
  • Final bitonic sequence: [2, 3, 4, 6] + [9, 7, 5, 4, 3] = [2, 3, 4, 6, 9, 7, 5, 4, 3]

Time Complexity

The time complexity is O(n log n) where n is the length of the arrays, due to the binary search optimization used in finding the longest increasing subsequences.

Conclusion

This algorithm efficiently finds the longest bitonic sequence by combining the longest increasing subsequence from the first array with the longest decreasing subsequence from the second array. The binary search optimization makes it suitable for larger datasets.

Updated on: 2026-03-25T09:43:00+05:30

241 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements