给定大小为N的整数数组,您必须将其划分为最小数量的“严格增加的子序列”
例如:假设序列为{1、3、2、4},则答案为2。在这种情况下,第一个递增序列为{1、3、4},第二个为{2}。
例子:
Input : arr[] = {1 3 2 4}
Output: 2
There are two increasing subsequences {1, 3, 4} and {2}
Input : arr[] = {4 3 2 1}
Output : 4
Input : arr[] = {1 2 3 4}
Output : 1
Input : arr[] = {1 6 2 4 3}
Output : 3
如果我们关注示例,则可以看到最小递增子序列数等于最长递减子序列的长度,其中最长递减子序列中的每个元素代表一个递增子序列,因此可以在N * Log(N)时间中找到复杂度与最长递增子序列相同(通过将所有元素乘以-1)。
我们遍历所有元素,并在排序数组(多集)S中存储到目前为止找到的每个递增子序列中的最后一个元素,并且对于每个元素X,我们都使用S中的二进制搜索-选择小于X的最大元素-并用X替换它,这意味着我们将当前元素添加到以X结尾的递增子序列中;否则,如果S中不存在小于X的元素,则将其插入S中,形成新的递增子序列,依此类推直到最后一个元素而我们最后的答案将是S的大小。
CPP
// C++ program to count the Minimum number of
// increasing subsequences
#include
using namespace std;
int MinimumNumIncreasingSubsequences(int arr[], int n)
{
multiset last;
// last element in each increasing subsequence
// found so far
for (int i = 0; i < n; i++) {
// here our current element is arr[i]
multiset::iterator it = last.lower_bound(arr[i]);
// iterator to the first element larger
// than or equal to arr[i]
if (it == last.begin())
// if all the elements in last larger
// than or to arr[i] then insert it into last
last.insert(arr[i]);
else {
it--;
// the largest element smaller than arr[i] is the number
// before *it which is it--
last.erase(it); // erase the largest element smaller than arr[i]
last.insert(arr[i]); // and replace it with arr[i]
}
}
return last.size(); // our answer is the size of last
}
// Driver program
int main()
{
int arr[] = { 8, 4, 1, 2, 9 };
int n = sizeof(arr) / sizeof(int);
cout << "Minimum number of increasing subsequences are : "
<< MinimumNumIncreasingSubsequences(arr, n);
return 0;
}
Java
// Java program for the above approach
import java.util.*;
public class Main {
static int longestDecrasingSubsequence(int A[], int N)
{
// Initialise Dp array
int dp[] = new int[N + 1];
Arrays.fill(dp, Integer.MAX_VALUE);
// All the elements are in range
// of Integer minvalue
// to maxvalue
// dp[i] indicate the min element
// of subsequence of
// length i is dp[i]
dp[0] = Integer.MIN_VALUE;
// For each number search for the correct position
// of number and insert the number in array
for (int i = 0; i < N; i++) {
// search for th position
int index = search(dp, A[i]);
// update the dp array
if (index != -1)
dp[index] = Math.min(dp[index], A[i]);
}
int len = 0;
for (int i = 1; i <= N; i++) {
if (dp[i] != Integer.MAX_VALUE)
len = Math.max(i, len);
}
return len;
}
// to search for correct position of num in array dp
static int search(int dp[], int num)
{
// initialise low,high and ans
int low = 0, high = dp.length - 1;
int ans = -1;
while (low <= high) {
// get mid
int mid = low + (high - low) / 2;
// if mid element is >=num search for left half
if (dp[mid] >= num) {
ans = mid;
high = mid - 1;
}
else
low = mid + 1;
}
return ans;
}
// Driver Code
public static void main(String args[])
{
int n = 4;
int a[] = { 1, 2, 3, 4 };
for (int i = 0; i < n; i++)
a[i] = -a[i];
System.out.print(longestDecrasingSubsequence(a, n));
}
}
Minimum number of increasing subsequences are : 3
时间复杂度:O(N log(N))
辅助空间:O(N)
方法2 :的想法是找到最长的递减子序列
- 初始化长度为n的dp数组。
- 反转数组的所有元素。
- 对于数组中的每个元素。
- 如果dp数组中的当前元素找到索引。
- 找到有效的最大索引。
- dp [i]表示以长度i子序列结尾的最小元素。
下面是上述方法的实现:
Java
// Java program for the above approach
import java.util.*;
public class Main {
static int longestDecrasingSubsequence(int A[], int N)
{
// Initialise Dp array
int dp[] = new int[N + 1];
Arrays.fill(dp, Integer.MAX_VALUE);
// All the elements are in range
// of Integer minvalue
// to maxvalue
// dp[i] indicate the min element
// of subsequence of
// length i is dp[i]
dp[0] = Integer.MIN_VALUE;
// For each number search for the correct position
// of number and insert the number in array
for (int i = 0; i < N; i++) {
// search for th position
int index = search(dp, A[i]);
// update the dp array
if (index != -1)
dp[index] = Math.min(dp[index], A[i]);
}
int len = 0;
for (int i = 1; i <= N; i++) {
if (dp[i] != Integer.MAX_VALUE)
len = Math.max(i, len);
}
return len;
}
// to search for correct position of num in array dp
static int search(int dp[], int num)
{
// initialise low,high and ans
int low = 0, high = dp.length - 1;
int ans = -1;
while (low <= high) {
// get mid
int mid = low + (high - low) / 2;
// if mid element is >=num search for left half
if (dp[mid] >= num) {
ans = mid;
high = mid - 1;
}
else
low = mid + 1;
}
return ans;
}
// Driver Code
public static void main(String args[])
{
int n = 4;
int a[] = { 1, 2, 3, 4 };
for (int i = 0; i < n; i++)
a[i] = -a[i];
System.out.print(longestDecrasingSubsequence(a, n));
}
}
1