📌  相关文章
📜  为具有重复元素的数组严格获得LIS所需的最小连接|套装2

📅  最后修改于: 2021-05-08 17:58:02             🧑  作者: Mango

给定大小为n的数组A [] ,其中数组中可以包含重复元素。我们必须找到序列A所需的最小串联,才能严格获得最长增长子序列。对于数组A [],我们遵循基于1的索引。

例子:

方法:
为了解决上述问题,第一个观察结果是严格增加的子序列的长度始终等于序列A []中存在的唯一元素的数量。因此,子序列的最大长度等于不同元素的数量。要解决此问题,请执行以下步骤:

  • 初始化一个变量,比方说ans为1,然后将序列分成左半子序列和右半子序列两半。将leftSeq初始化为NULL,并将原始序列复制到rightSeq中。
  • 遍历右侧子序列以找到由变量CurrElement表示的最小元素并存储其索引。
  • 现在更新左子序列和右子序列,其中leftSeq用给定序列更新到索引,该索引将最小元素存储在右子序列中。以及从最小索引值到结尾的给定序列的rightSeq。
  • 遍历数组以获取下一个最小元素并更新CurrElement的值。如果rightSeq中没有这样的最小值,则必须在leftSeq中。在左子序列中找到该元素的索引并存储其索引。
  • 现在再次更新左右子序列的值,其中leftSeq =给定序列直到第k个索引,rightSeq =给定序列从第k个索引到结束。重复该过程,直到达到阵列限制。
  • ans的值增加1,并在CurrElement等于最高元素时停止。

下面是上述方法的实现:

C++
// C++ implementation to Find the minimum
// concatenation required to get strictly
// Longest Increasing Subsequence for the
// given array with repetitive elements
#include 
using namespace std;
 
int LIS(int arr[], int n)
{
    // ordered map containing value and
    // a vector containing index of
    // it's occurrences
    map > m;
 
    // Mapping index with their values
    // in ordered map
    for (int i = 0; i < n; i++)
        m[arr[i]].push_back(i);
 
    // k refers to present minimum index
    int k = n;
 
    // Stores the number of concatenation
    // required
    int ans = 0;
 
    // Iterate over map m
    for (auto it = m.begin(); it != m.end();
                                       it++) {
        // it.second refers to the vector
        // containing all corresponding
        // indexes
 
        // it.second.back refers to the
        // last element of corresponding vector
 
        if (it->second.back() < k) {
            k = it->second[0];
            ans += 1;
        }
        else
 
            // find the index of next minimum
            // element in the sequence
            k = *lower_bound(it->second.begin(),
                            it->second.end(), k);
    }
 
    // Return the final answer
    cout << ans << endl;
}
 
// Driver program
int main()
{
    int arr[] = { 1, 3, 2, 1, 2 };
 
    int n = sizeof(arr) / sizeof(arr[0]);
 
    LIS(arr, n);
 
    return 0;
}


Java
// Java implementation to Find the minimum
// concatenation required to get strictly
// Longest Increasing Subsequence for the
// given array with repetitive elements
import java.io.*;
import java.util.*;
 
class GFG{
 
static void LIS(int arr[], int n)
{
     
    // ordered map containing value and
    // a vector containing index of
    // it's occurrences
    TreeMap> m = new TreeMap>();
     
    // Mapping index with their values
    // in ordered map
    for(int i = 0; i < n; i++)
    {
        List indexes;
         
        if (m.containsKey(arr[i]))
        {
            indexes = m.get(arr[i]);
        }
        else
        {
            indexes = new ArrayList();
        }
        indexes.add(i);
        m.put(arr[i], indexes);
    }
     
    // k refers to present minimum index
    int k = n;
 
    // Stores the number of concatenation
    // required
    int ans = 0;
 
    // Iterate over map m
    for(Map.Entry> it : m.entrySet())
    {
         
        // List containing all corresponding
        // indexes
        List indexes = it.getValue();
 
        if (indexes.get(indexes.size() - 1) < k)
        {
            k = indexes.get(0);
            ans++;
        }
        else
         
            // Find the index of next minimum
            // element in the sequence
            k = lower_bound(indexes, k);
    }
     
    // Return the final answer
    System.out.println(ans);
}
 
static int lower_bound(List indexes,
                       int k)
{
    int low = 0, high = indexes.size() - 1;
 
    while (low < high)
    {
        int mid = (low + high) / 2;
        if (indexes.get(mid) < k)
            low = mid + 1;
        else
            high = mid;
    }
    return indexes.get(low);
}
 
// Driver code
public static void main(String[] args)
{
    int arr[] = { 1, 3, 2, 1, 2 };
 
    int n = arr.length;
 
    LIS(arr, n);
}
}
 
// This code is contributed by jithin


Python3
# Python3 implementation to
# Find the minimum concatenation
# required to get strictly Longest
# Increasing Subsequence for the
# given array with repetitive elements
from bisect import bisect_left
 
def LIS(arr, n):
   
    # ordered map containing
    # value and a vector containing
    # index of it's occurrences
    #  > m;
    m = {}
 
    # Mapping index with their
    # values in ordered map
    for i in range(n):
        m[arr[i]] = m.get(arr[i], [])
        m[arr[i]].append(i)
 
    # k refers to present
    # minimum index
    k = n
 
    # Stores the number of
    # concatenation required
    ans = 1
 
    # Iterate over map m
    for key, value in m.items():
       
        # it.second refers to the
        # vector containing all
        # corresponding indexes
 
        # it.second.back refers
        # to the last element of
        # corresponding vector
        if (value[len(value) - 1] < k):
            k = value[0]
            ans += 1
        else:
           
            # find the index of next
            # minimum element in the
            # sequence
            k = bisect_left(value, k)
 
    # Return the final
    # answer
    print(ans)
 
# Driver code
if __name__ == '__main__':
   
    arr =  [1, 3, 2, 1, 2]
    n = len(arr)
    LIS(arr, n)
 
# This code is contributed by bgangwar59


输出:
2














时间复杂度: O(n * log n)