给定大小为n的数组A [] ,其中数组中可以包含重复元素。我们必须找到序列A所需的最小串联,才能严格获得最长增长子序列。对于数组A [],我们遵循基于1的索引。
例子:
Input: A = {2, 1, 2, 4, 3, 5}
Output: 2
Explanation:
We can concatenate A two times as [2, 1, 2, 4, 3, 5, 2, 1, 2, 4, 3, 5] and then output for index 2, 3, 5, 10, 12 which gives sub-sequence as 1 -> 2 -> 3 -> 4 -> 5.
Input: A = {1, 3, 2, 1, 2}
Output: 2
Explanation:
We can concatenate A two times as [1, 3, 2, 1, 2, 1, 3, 2, 1, 2] and then output for index 1, 3, 7 which gives sub-sequence as 1 -> 2 -> 3.
方法:
为了解决上述问题,第一个观察结果是严格增加的子序列的长度始终等于序列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)