📜  查找最长的双音序列,以使增加和减少的部分来自两个不同的阵列

📅  最后修改于: 2021-04-23 20:20:26             🧑  作者: Mango

我们得到两个阵列,我们需要找到最长的双音序列,使得增加的部分必须来自第一个阵列,并且应该是第一个阵列的子序列。同样,的递减部分必须来自第二个数组,并且应该是它的子序列。
例子:

Input : arr1[] = {1, 5, 2, 4, 3, 5}, 
        arr2[] = {8, 6, 4, 7, 3, 2}
Output : 1, 2, 4, 5, 8, 6, 4, 3, 2

Input : arr1[] = {2, 0, 1, 3, 4}, 
        arr2[] = {5, 3, 2, 1}
Output : 0, 1, 2, 3, 4, 5, 3, 2, 1


这个想法是使用array1的最大递增序列和array2的最大递减序列,然后将两者组合以获得结果。

C++
// CPP to find largest bitonic sequence such that
#include 
using namespace std;
 
vector res;
 
// utility Binary search
int GetCeilIndex(int arr[], vector& T, int l,
                                   int r, int key)
{
    while (r - l > 1) {
        int m = l + (r - l) / 2;
        if (arr[T[m]] >= key)
            r = m;
        else
            l = m;
    }
    return r;
}
 
// function to find LIS in reverse form
void LIS(int arr[], int n)
{
    // Add boundary case, when array n is zero
    // Depend on smart pointers
    vector tailIndices(n, 0); // Initialized with 0
    vector prevIndices(n, -1); // initialized with -1
 
    int len = 1; // it will always point to empty location
    for (int i = 1; i < n; i++) {
 
        // new smallest value
        if (arr[i] < arr[tailIndices[0]])            
            tailIndices[0] = i;
 
        // arr[i] wants to extend largest subsequence
        else if (arr[i] > arr[tailIndices[len - 1]]) {           
            prevIndices[i] = tailIndices[len - 1];
            tailIndices[len++] = i;
        }
          
        // arr[i] wants to be a potential candidate of
        // future subsequence
        // It will replace ceil value in tailIndices
        else {
            int pos = GetCeilIndex(arr, tailIndices, -1,
                                        len - 1, arr[i]);
            prevIndices[i] = tailIndices[pos - 1];
            tailIndices[pos] = i;
        }
    }
 
    // put LIS into vector
    for (int i = tailIndices[len - 1]; i >= 0; i = prevIndices[i])
        res.push_back(arr[i]);
}
 
// function for finding longest bitonic seq
void longestBitonic(int arr1[], int n1, int arr2[], int n2)
{
    // find LIS of array 1 in reverse form
    LIS(arr1, n1);
 
    // reverse res to get LIS of first array
    reverse(res.begin(), res.end());
 
    // reverse array2 and find its LIS
    reverse(arr2, arr2 + n2);
    LIS(arr2, n2);
 
    // print result
    for (int i = 0; i < res.size(); i++)
        cout << res[i] << " ";
}
 
// driver preogram
int main()
{
    int arr1[] = { 1, 2, 4, 3, 2 };
    int arr2[] = { 8, 6, 4, 7, 8, 9 };
    int n1 = sizeof(arr1) / sizeof(arr1[0]);
    int n2 = sizeof(arr2) / sizeof(arr2[0]);
    longestBitonic(arr1, n1, arr2, n2);
    return 0;
}


Java
// Java to find largest bitonic sequence such that
import java.util.*;
 
class GFG
{
    static Vector res = new Vector<>();
 
    // utility Binary search
    static Integer GetCeilIndex(Integer[] arr, Integer[] T,
                                Integer l, Integer r, Integer key)
    {
        while (r - l > 1)
        {
            Integer m = l + (r - l) / 2;
            if (arr[T[m]] >= key)
                r = m;
            else
                l = m;
        }
        return r;
    }
 
    // function to find LIS in reverse form
    static void LIS(Integer[] arr, Integer n)
    {
 
        // Add boundary case, when array n is zero
        // Depend on smart pointers
        Integer[] tailIndices = new Integer[n];
        Integer[] prevIndices = new Integer[n];
        Arrays.fill(tailIndices, 0); // Initialized with 0
        Arrays.fill(prevIndices, -1); // initialized with -1
 
        Integer len = 1; // it will always point to empty location
        for (Integer i = 1; i < n; i++)
        {
            // new smallest value
            if (arr[i] < arr[tailIndices[0]])
                tailIndices[0] = i;
 
            // arr[i] wants to extend largest subsequence
            else if (arr[i] > arr[tailIndices[len - 1]])
            {
                prevIndices[i] = tailIndices[len - 1];
                tailIndices[len++] = i;
            }
 
            // arr[i] wants to be a potential candidate of
            // future subsequence
            // It will replace ceil value in tailIndices
            else
            {
                Integer pos = GetCeilIndex(arr,
                            tailIndices, -1, len - 1, arr[i]);
                prevIndices[i] = tailIndices[pos - 1];
                tailIndices[pos] = i;
            }
        }
 
        // put LIS into vector
        for (Integer i = tailIndices[len - 1]; i >= 0; i = prevIndices[i])
            res.add(arr[i]);
    }
 
    // function for finding longest bitonic seq
    static void longestBitonic(Integer[] arr1, Integer n1,
                                Integer[] arr2, Integer n2)
    {
        // find LIS of array 1 in reverse form
        LIS(arr1, n1);
 
        // reverse res to get LIS of first array
        Collections.reverse(res);
 
        // reverse array2 and find its LIS
        Collections.reverse(Arrays.asList(arr2));
        LIS(arr2, n2);
 
        // print result
        for (Integer i = 0; i < res.size(); i++)
            System.out.print(res.elementAt(i) + " ");
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        Integer[] arr1 = { 1, 2, 4, 3, 2 };
        Integer[] arr2 = { 8, 6, 4, 7, 8, 9 };
        Integer n1 = arr1.length;
        Integer n2 = arr2.length;
        longestBitonic(arr1, n1, arr2, n2);
    }
}
 
// This code is contributed by
// sanjeev2552


Python3
# Python3 to find largest bitonic sequence such that
res = []
 
# utility Binary search
def GetCeilIndex(arr,T, l,r, key):
    while (r - l > 1):
        m = l + (r - l) // 2;
        if (arr[T[m]] >= key):
            r = m
        else:
            l = m
    return r
 
# function to find LIS in reverse form
def LIS(arr, n):
     
    # Add boundary case, when array n is zero
    # Depend on smart pointers
    tailIndices = [0]*(n) #Initialized with 0
    prevIndices = [-1]*(n) #initialized with -1
 
    leN = 1 # it will always poto empty location
    for i in range(1, n):
 
        # new smallest value
        if (arr[i] < arr[tailIndices[0]]):
            tailIndices[0] = i
 
        # arr[i] wants to extend largest subsequence
        elif (arr[i] > arr[tailIndices[leN - 1]]):
            prevIndices[i] = tailIndices[leN - 1]
            tailIndices[leN] = i
            leN += 1
 
        # arr[i] wants to be a potential candidate of
        # future subsequence
        # It will replace ceil value in tailIndices
        else:
            pos = GetCeilIndex(arr, tailIndices, -1,
                               leN - 1, arr[i])
            prevIndices[i] = tailIndices[pos - 1]
            tailIndices[pos] = i
 
    # put LIS into vector
    i = tailIndices[leN - 1]
    while(i >= 0):
         
        # print(i)
        res.append(arr[i])
        i = prevIndices[i]
 
# function for finding longest bitonic seq
def longestBitonic(arr1, n1, arr2, n2):
    global res
     
    # find LIS of array 1 in reverse form
    LIS(arr1, n1)
 
    # reverse res to get LIS of first array
    res = res[::-1]
 
    # reverse array2 and find its LIS
    arr2 = arr2[::-1]
    LIS(arr2, n2)
 
    # print result
    for i in res:
        print(i,end=" ")
 
# Driver program
 
arr1 = [1, 2, 4, 3, 2]
arr2 = [8, 6, 4, 7, 8, 9]
n1 = len(arr1)
n2 = len(arr2)
longestBitonic(arr1, n1, arr2, n2);
 
# This code is contributed by mohit kumar 29


C#
// C# to find largest bitonic
// sequence
using System;
using System.Collections.Generic;
class GFG{
 
static List res = new List();
 
// Reverse array
static int[] reverse(int []a)
{
  int i, n = a.Length, t;
  for (i = 0; i < n / 2; i++)
  {
    t = a[i];
    a[i] = a[n - i - 1];
    a[n - i - 1] = t;
  }
  return a;
}
   
// Utility Binary search
static int GetCeilIndex(int[] arr, int[] T,
                        int l, int r, int key)
{
  while (r - l > 1)
  {
    int m = l + (r - l) / 2;
    if (arr[T[m]] >= key)
      r = m;
    else
      l = m;
  }
  return r;
}
 
// Function to find LIS in reverse form
static void LIS(int[] arr, int n)
{
  // Add boundary case,
  // when array n is zero
  // Depend on smart pointers
  int[] tailIndices = new int[n];
  int[] prevIndices = new int[n];
  for(int i = 0; i < n; i++)
  {
    tailIndices[i] = 0;
    prevIndices[i] = -1;
  }
  int len = 1;
   
  // It will always point
  // to empty location
  for (int i = 1; i < n; i++)
  {
    // New smallest value
    if (arr[i] < arr[tailIndices[0]])
      tailIndices[0] = i;
 
    // arr[i] wants to extend
    // largest subsequence
    else if (arr[i] > arr[tailIndices[len - 1]])
    {
      prevIndices[i] = tailIndices[len - 1];
      tailIndices[len++] = i;
    }
 
    // arr[i] wants to be
    // a potential candidate of
    // future subsequence
    // It will replace ceil
    // value in tailIndices
    else
    {
      int pos = GetCeilIndex(arr, tailIndices,
                             -1, len - 1, arr[i]);
      prevIndices[i] = tailIndices[pos - 1];
      tailIndices[pos] = i;
    }
  }
 
  // Put LIS into vector
  for (int i = tailIndices[len - 1];
           i >= 0; i = prevIndices[i])
    res.Add(arr[i]);
}
 
// Function for finding longest bitonic seq
static void longestBitonic(int[] arr1, int n1, 
                           int[] arr2, int n2)
{
  // Find LIS of array 1
  // in reverse form
  LIS(arr1, n1);
 
  // Reverse res to get
  // LIS of first array
  res.Reverse();
 
  // Reverse array2 and
  // find its LIS
  arr2 = reverse(arr2);
  LIS(arr2, n2);
 
  // Print result
  for (int i = 0; i < res.Count; i++)
    Console.Write(res[i] + " ");
}
 
// Driver Code
public static void Main(String[] args)
{
  int[] arr1 = {1, 2, 4, 3, 2};
  int[] arr2 = {8, 6, 4, 7, 8, 9};
  int n1 = arr1.Length;
  int n2 = arr2.Length;
  longestBitonic(arr1, n1, arr2, n2);
}
}
 
// This code is contributed by gauravrajput1


输出:

1 2 3 8 6 4