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


Suppose we have two arrays; we have to find the longest possible bitonic sequence so that the increasing part should be from first array and should be a subsequence of first array. similarly decreasing part of must be from second array and a subsequence of the second one.

So, if the input is like A = [2, 6, 3, 5, 4, 6], B = [9, 7, 5, 8, 4, 3], then the output will be [2, 3, 4, 6, 9, 7, 5, 4, 3]

To solve this, we will follow these steps −

  • Define a function index_ceiling() . This will take arr, T, left, right, key

  • while right - left > 1, do

    • mid := left +(right - left) / 2;

    • if arr[T[mid]] >= key, then

      • right := mid

    • otherwise,

      • left := mid

  • return right

  • Define a function long_inc_seq() . This will take A

  • n := size of A

  • tails_idx := an array of size n, fill with 0

  • prev_idx := an array of size n, fill with -1

  • length := 1

  • for i in range 1 to n, do

    • if A[i] < A[tails_idx[0]], then

      • tails_idx[0] := i

    • otherwise when A[i] > A[tails_idx[length - 1]], then

      • prev_idx[i] := tails_idx[length - 1]

      • tails_idx[length] := i

      • length := length + 1

    • otherwise,

      • pos := index_ceiling(A, tails_idx, -1, length - 1, A[i])

      • prev_idx[i] := tails_idx[pos - 1]

      • tails_idx[pos] := i

  • i := tails_idx[length - 1]

  • while i >= 0, do

    • insert A[i] at the end of answer

    • i := prev_idx[i]

  • From the main method, do the following −

  • n1 := size of A, n2 := size of B

  • long_inc_seq(A)

  • answer := reverse answer

  • B := reverse B

  • long_inc_seq(B)

  • return answer

Example

Let us see the following implementation to get better understanding −

answer = []
def index_ceiling(arr,T, left,right, key):
   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):
   n = len(A)
   tails_idx = [0]*(n)
   prev_idx = [-1]*(n)
   length = 1
   for i in range(1, n):
      if (A[i] < A[tails_idx[0]]):
         tails_idx[0] = i
      elif (A[i] > A[tails_idx[length - 1]]):
         prev_idx[i] = tails_idx[length - 1]
         tails_idx[length] = i
         length += 1
      else:
         pos = index_ceiling(A, tails_idx, -1, length - 1, A[i])
         prev_idx[i] = tails_idx[pos - 1]
         tails_idx[pos] = i
   i = tails_idx[length - 1]
   while(i >= 0):
      answer.append(A[i])
      i = prev_idx[i]
def long_bitonic(A,B):
   n1 = len(A)
   n2 = len(B)
   global answer
   long_inc_seq(A)
   answer = answer[::-1]
   B = B[::-1]
   long_inc_seq(B)
A = [2, 6, 3, 5, 4, 6]
B = [9, 7, 5, 8, 4, 3]
long_bitonic(A,B)
print(answer)

Input

[2, 6, 3, 5, 4, 6], [9, 7, 5, 8, 4, 3]

Output

[2, 3, 4, 6, 9, 7, 5, 4, 3]

Updated on: 25-Aug-2020

57 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements