给定一个大小为 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)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。