Sunday, September 22, 2024
Google search engine
HomeLanguagesDynamic ProgrammingMinimum number of increasing subsequences

Minimum number of increasing subsequences

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:
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




// 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 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 to count the Minimum number of
// increasing subsequences
import java.util.*;
 
public class Main {
    static int MinimumNumIncreasingSubsequences(int[] arr,
                                                int n)
    {
        TreeSet<Integer> last = new TreeSet<>();
        // last element in each  increasing subsequence
        // found so far
        for (int i = 0; i < n; i++) {
            Integer it = last.ceiling(arr[i]);
            if (it == null)
                // if all the elements in last larger
                // than or to arr[i] then insert it into
                // last
                last.add(arr[i]);
            else {
                last.remove(it);
                last.add(arr[i]);
            }
        }
 
        return last.size();
    }
 
    // Driver program
    public static void main(String[] args)
    {
        int[] arr = { 8, 4, 1, 2, 9 };
        int n = arr.length;
        System.out.println(
            "Minimum number of increasing subsequences are: "
            + MinimumNumIncreasingSubsequences(arr, n));
    }
}
//contributed by Aditya Sharma


Python3




# Python code implementation
def MinimumNumIncreasingSubsequences(arr, n):
    last = set()
     
    # last element in each increasing subsequence found
    # so far
    for i in range(n):
        it = -1
        for value in last:
            if value >= arr[i]:
                it = value
                break
        if it == -1:
           
            # if all the elements in last larger than
            # or to arr[i] then insert it into last
            last.add(arr[i])
        else:
            last.remove(it)
            last.add(arr[i])
    return len(last)
 
# Code
arr = [8, 4, 1, 2, 9]
n = len(arr)
print("Minimum number of increasing subsequences are:",
      MinimumNumIncreasingSubsequences(arr, n))
 
# This code is contributed by sankar.


C#




// C# program to count the minimum no. of increasing
// subsequences
 
using System;
using System.Collections.Generic;
 
public class GFG {
 
    static int MinimumNumIncreasingSubsequences(int[] arr,
                                                int n)
    {
        HashSet<int> last = new HashSet<int>();
        // last element in each increasing subsequence found
        // so far
        for (int i = 0; i < n; i++) {
            int it = -1;
            foreach(int value in last)
            {
                if (value >= arr[i]) {
                    it = value;
                    break;
                }
            }
            if (it == -1)
                // if all the elements in last larger than
                // or to arr[i] then insert it into last
                last.Add(arr[i]);
            else {
                last.Remove(it);
                last.Add(arr[i]);
            }
        }
        return last.Count;
    }
 
    static public void Main()
    {
 
        // Code
        int[] arr = { 8, 4, 1, 2, 9 };
        int n = arr.Length;
        Console.WriteLine(
            "Minimum number of increasing subsequences are: "
            + MinimumNumIncreasingSubsequences(arr, n));
    }
}
 
// This code is contributed by karthik.


Javascript




// Javascript program to count the Minimum number of
// increasing subsequences
 
function MinimumNumIncreasingSubsequences(arr, n) {
  let last = new Set();
  // last element in each increasing subsequence
  // found so far
  for (let i = 0; i < n; i++) {
      let it = null;
      for (let value of last) {
          if (value >= arr[i]) {
              it = value;
              break;
          }
      }
  if (it === null)
    // if all the elements in last larger
    // than or to arr[i] then insert it into
    // last
    last.add(arr[i]);
  else {
    last.delete(it);
    last.add(arr[i]);
  }
}
 
return last.size;
}
 
// Driver program
let arr = [8, 4, 1, 2, 9];
let n = arr.length;
console.log(
"Minimum number of increasing subsequences are: " +
MinimumNumIncreasingSubsequences(arr, n));


Output

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++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// To search for correct position of num in array dp
int 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 integer 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 the 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 code
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;
}
 
// This code is contributed by shinjanpatra


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 the 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));
    }
}


Python3




# Python program for the above approach
import sys
 
def longestDecrasingSubsequence(A,N):
 
    # Initialise Dp array
    dp = [sys.maxsize for i in range(N+1)]
 
    # 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] = -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 the 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 dp
def 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 Code
n = 4
a = [ 1, 2, 3, 4 ]
for i in range(n):
    a[i] = -a[i]
 
print(longestDecrasingSubsequence(a, n))
 
# This code is contributed by shinjanpatra


C#




// C# code for the above approach
using System;
class GFG
{
  static int longestDecrasingSubsequence(int[] A, int N)
  {
    // Initialise Dp array
    int[] dp = new int[N + 1];
    for (int i = 0; i < dp.Length; i++)
      dp[i] = int.MaxValue;
 
    // 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]
      = int.MinValue;
 
    // 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 the 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] != int.MaxValue)
        len = Math.Max(i, len);
    }
    return len/4;
  }
 
  // 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];
    Console.WriteLine(
      longestDecrasingSubsequence(a, n));
  }
}
 
// This code is contributed by pradeepkumarppk2003


Javascript




// JS program for the above approach
 
// To search for correct position of num in array dp
function search(dp, num) {
 
    // Initialise low,high and ans
    let low = 0, high = dp.length - 1;
    let ans = -1;
    while (low <= high) {
 
        // Get mid
        let mid = low + Math.floor((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;
}
 
function longestDecrasingSubsequence(A, N) {
 
    // Initialise Dp array
    let dp = new Array(N + 1).fill(Number.MAX_SAFE_INTEGER);
 
    // 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] = Number.MIN_SAFE_INTEGER;
 
    // For each number search for the correct position
    // of number and insert the number in array
    for (let i = 0; i < N; i++) {
 
        // search for the position
        let index = search(dp, A[i]);
 
        // update the dp array
        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;
}
 
// Driver code
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));
 
// This code is contributed by lokeshpotta20.


Output

1

Time complexity: O(N * log(N))
Auxiliary Space: O(N)

Feeling lost in the world of random DSA topics, wasting time without progress? It’s time for a change! Join our DSA course, where we’ll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

Dominic Rubhabha-Wardslaus
Dominic Rubhabha-Wardslaushttp://wardslaus.com
infosec,malicious & dos attacks generator, boot rom exploit philanthropist , wild hacker , game developer,
RELATED ARTICLES

Most Popular

Recent Comments