Given an array of integers of size N, you have to divide it into the minimum number of “strictly increasing subsequences”
For example: let the sequence be {1, 3, 2, 4}, then the answer would be 2. In this case, the first increasing sequence would be {1, 3, 4} and the second would be {2}.
Examples:
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
If we focus on the example we can see that the Minimum number of increasing subsequences equals to the length of longest decreasing subsequence where each element from the longest decreasing subsequence represents an increasing subsequence, so it can be found in N*Log(N) time complexity in the same way as longest increasing subsequence by multiplying all the elements with -1.
We iterator over all elements and store in a sorted array (multiset) S the last element in each one of the increasing subsequences found so far and for every element X, we pick the largest element smaller than X -using binary search- in the S and replace it with X which means that we added the current element to increasing subsequence ending with X, otherwise, if there is no element smaller than X in S we insert it in S which forms a new increasing subsequence and so on until the last element and our answer in the last will be the size of S.
CPP
#include <bits/stdc++.h>
using namespace std;
int MinimumNumIncreasingSubsequences( int arr[], int n)
{
multiset< int > last;
for ( int i = 0; i < n; i++) {
multiset< int >::iterator it = last.lower_bound(arr[i]);
if (it == last.begin())
last.insert(arr[i]);
else {
it--;
last.erase(it);
last.insert(arr[i]);
}
}
return last.size();
}
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;
}
|
OutputMinimum number of increasing subsequences are : 3
Time complexity: O(N log(N))
Auxiliary Space : O(N)
Approach 2: The idea is to find the longest decreasing subsequence
- Initialize a dp array of length n.
- Inverting all the elements of the array.
- for each element in the array.
- find the index if the current element in the dp array.
- find the maximum index which is valid.
- dp[i] indicate that minimum element ending at the length i subsequence.
Below is the implementation of above approach :
C++
#include <bits/stdc++.h>
using namespace std;
int search(vector< int >dp, int num){
int low = 0,high = dp.size() - 1;
int ans = -1;
while (low <= high){
int mid = low + ((high - low) / 2);
if (dp[mid] >= num){
ans = mid;
high = mid - 1;
}
else
low = mid + 1;
}
return ans;
}
int longestDecrasingSubsequence(vector< int >A, int N){
vector< int >dp(N+1,INT_MAX);
dp[0] = INT_MIN;
for ( int i = 0; i < N; i++){
int index = search(dp, A[i]);
if (index != -1)
dp[index] = min(dp[index], A[i]);
}
int Len = 0;
for ( int i = 1; i < N; i++){
if (dp[i] != INT_MAX)
Len = max(i, Len);
}
return Len;
}
int main()
{
int n = 4;
vector< int > a = { 1, 2, 3, 4 };
for ( int i=0;i<n;i++)
a[i] = -a[i];
cout << longestDecrasingSubsequence(a, n) << endl;
return 0;
}
|
Java
import java.util.*;
public class Main {
static int longestDecrasingSubsequence( int A[], int N)
{
int dp[] = new int [N + 1 ];
Arrays.fill(dp, Integer.MAX_VALUE);
dp[ 0 ] = Integer.MIN_VALUE;
for ( int i = 0 ; i < N; i++) {
int index = search(dp, A[i]);
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;
}
static int search( int dp[], int num)
{
int low = 0 , high = dp.length - 1 ;
int ans = - 1 ;
while (low <= high) {
int mid = low + (high - low) / 2 ;
if (dp[mid] >= num) {
ans = mid;
high = mid - 1 ;
}
else
low = mid + 1 ;
}
return ans;
}
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));
}
}
|
Python3
import sys
def longestDecrasingSubsequence(A,N):
dp = [sys.maxsize for i in range (N + 1 )]
dp[ 0 ] = - sys.maxsize - 1
for i in range (N):
index = search(dp, A[i])
if (index ! = - 1 ):
dp[index] = min (dp[index], A[i])
Len = 0
for i in range ( 1 ,N):
if (dp[i] ! = sys.maxsize):
Len = max (i, Len )
return Len
def search(dp, num):
low,high = 0 , len (dp) - 1
ans = - 1
while (low < = high):
mid = low + (high - low) / / 2
if (dp[mid] > = num):
ans = mid
high = mid - 1
else :
low = mid + 1
return ans
n = 4
a = [ 1 , 2 , 3 , 4 ]
for i in range (n):
a[i] = - a[i]
print (longestDecrasingSubsequence(a, n))
|
C#
using System;
class GFG
{
static int longestDecrasingSubsequence( int [] A, int N)
{
int [] dp = new int [N + 1];
for ( int i = 0; i < dp.Length; i++)
dp[i] = int .MaxValue;
dp[0]
= int .MinValue;
for ( int i = 0; i < N; i++) {
int index = search(dp, -A[i]);
if (index != -1)
dp[index] = Math.Min(dp[index], -A[i]);
}
int len = 0;
for ( int i = 1; i <= N; i++) {
if (dp[i] != int .MaxValue)
len = Math.Max(i, len);
}
return len/4;
}
static int search( int [] dp, int num)
{
int low = 0, high = dp.Length - 1;
int ans = -1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (dp[mid] >= num) {
ans = mid;
high = mid - 1;
}
else
low = mid + 1;
}
return ans;
}
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];
Console.WriteLine(
longestDecrasingSubsequence(a, n));
}
}
|
Javascript
function search(dp, num) {
let low = 0, high = dp.length - 1;
let ans = -1;
while (low <= high) {
let mid = low + Math.floor((high - low) / 2);
if (dp[mid] >= num) {
ans = mid;
high = mid - 1;
}
else
low = mid + 1;
}
return ans;
}
function longestDecrasingSubsequence(A, N) {
let dp = new Array(N + 1).fill(Number.MAX_SAFE_INTEGER);
dp[0] = Number.MIN_SAFE_INTEGER;
for (let i = 0; i < N; i++) {
let index = search(dp, A[i]);
if (index !== -1)
dp[index] = Math.min(dp[index], A[i]);
}
let Len = 0;
for (let i = 1; i < N; i++) {
if (dp[i] !== Number.MAX_SAFE_INTEGER)
Len = Math.max(i, Len);
}
return Len;
}
let n = 4;
let a = [1, 2, 3, 4];
for (let i = 0; i < n; i++)
a[i] = -a[i];
console.log(longestDecrasingSubsequence(a, n));
|
Please Login to comment...