Minimum number of increasing subsequences

22 Jun, 2022
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 : 4Input : arr[] = {1 2 3 4} Output : 1Input : 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
// C++ program to count the Minimum number of// increasing subsequences#include <bits/stdc++.h>using namespace std; int MinimumNumIncreasingSubsequences(int arr[], int n){    multiset<int> 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<int>::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 programint 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;}
Minimum 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++
Java
Python3
// C++ program for the above approach#include <bits/stdc++.h>using namespace std; // To search for correct position of num in array dpint search(vector<int>dp, int num){     // Initialise low,high and ans    int low = 0,high = dp.size() - 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;} int longestDecrasingSubsequence(vector<int>A,int N){     // Initialise Dp array    vector<int>dp(N+1,INT_MAX);     // All the elements are in range    // of leteger minvalue    // to maxvalue    // dp[i] indicate the min element    // of subsequence of    // length i is dp[i]    dp[0] = INT_MIN;         // 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] = 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;} // Driver codeint 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;} // This code is contributed by shinjanpatra
// Java program for the above approachimport 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));    }}
# Python program for the above approachimport sys def longestDecrasingSubsequence(A,N):     # Initialise Dp array    dp = [sys.maxsize for i in range(N+1)]     # All the elements are in range    # of leteger minvalue    # to maxvalue    # dp[i] indicate the min element    # of subsequence of    # length i is dp[i]    dp[0] = -sys.maxsize -1         # For each number search for the correct position    # of number and insert the number in array    for i in range(N):         # search for th position        index = search(dp, A[i])         # update the dp array        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 # to search for correct position of num in array dpdef search(dp, num):     # initialise low,high and ans    low,high = 0, len(dp) - 1    ans = -1    while (low <= high):         # get mid        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 Coden = 4a = [ 1, 2, 3, 4 ]for i in range(n):    a[i] = -a[i] print(longestDecrasingSubsequence(a, n)) # This code is contributed by shinjanpatra
1
hemanthswarna1506
shinjanpatra
cpp-multiset
LIS
Competitive Programming
Dynamic Programming
Dynamic Programming
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Count of strings whose prefix match with the given string to a given length k
Most important type of Algorithms
The Ultimate Beginner's Guide For DSA
Find two numbers from their sum and XOR
C++: Methods of code shortening in competitive programming
Largest Sum Contiguous Subarray
Program for Fibonacci numbers
0-1 Knapsack Problem | DP-10
Longest Common Subsequence | DP-4
Subset Sum Problem | DP-25