Open In App

Minimum number of increasing subsequences

Last Updated : 23 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

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

Approach: To solve the problem, follow the below idea:

If we focus on the examples, 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 belongs to a single 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. 

Step-by-step approach:

  • Initialize a dp[] array of length N.
  • Multiply all the elements of the array with -1, so that our problem now gets reduced to finding the length of longest increasing subsequence.
  • Return the length of longest increasing subsequence using Binary Search.

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 longestIncreasingSubsequence(vector<int> arr, int N)
{
    vector<int> ans;

    // Initialize the answer vector with the
    // first element of nums
    ans.push_back(arr[0]);

    for (int i = 1; i < N; i++) {
        if (arr[i] > ans.back()) {

            // If the current number is greater
            // than the last element of the answer
            // vector, it means we have found a
            // longer increasing subsequence.
            // Hence, we append the current number
            // to the answer vector.
            ans.push_back(arr[i]);
        }
        else {

            // If the current number is not
            // greater than the last element of
            // the answer vector, we perform
            // a binary search to find the smallest
            // element in the answer vector that
            // is greater than or equal to the
            // current number.

            // The lower_bound function returns
            // an iterator pointing to the first
            // element that is not less than
            // the current number.
            int low = lower_bound(ans.begin(), ans.end(),
                                  arr[i])
                      - ans.begin();

            // We update the element at the
            // found position with the current number.
            // By doing this, we are maintaining
            // a sorted order in the answer vector.
            ans[low] = arr[i];
        }
    }

    // The length of the answer vector
    // represents the length of the
    // longest increasing subsequence.
    return ans.size();
}

// Driver code
int main()
{
    int N = 5;
    vector<int> arr{1, 6, 2, 4, 3};
    for (int i = 0; i < N; i++)
        arr[i] = -arr[i];

    cout << longestIncreasingSubsequence(arr, N) << endl;
    return 0;
}

// This code is contributed by shinjanpatra
Java
import java.util.*;

class Main {
    // To search for correct position of num in array dp
    static int search(ArrayList<Integer> 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.get(mid) >= num) {
                ans = mid;
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        return ans;
    }

    static int longestIncreasingSubsequence(ArrayList<Integer> arr, int N) {
        ArrayList<Integer> ans = new ArrayList<>();
        // Initialize the answer ArrayList with the first element of arr
        ans.add(arr.get(0));
        for (int i = 1; i < N; i++) {
            if (arr.get(i) > ans.get(ans.size() - 1)) {
                // If the current number is greater than the last element of the answer ArrayList,
                // it means we have found a longer increasing subsequence.
                // Hence, we append the current number to the answer ArrayList.
                ans.add(arr.get(i));
            } else {
                // If the current number is not greater than the last element of the answer ArrayList,
                // we perform a binary search to find the smallest element in the answer ArrayList
                // that is greater than or equal to the current number.
                int low = Collections.binarySearch(ans, arr.get(i));
                if (low < 0) {
                    low = -(low + 1);
                }
                // We update the element at the found position with the current number.
                // By doing this, we are maintaining a sorted order in the answer ArrayList.
                ans.set(low, arr.get(i));
            }
        }
        // The size of the answer ArrayList represents the length of the longest increasing subsequence.
        return ans.size();
    }

    // Driver code
    public static void main(String[] args) {
        int N = 5;
        ArrayList<Integer> arr = new ArrayList<>(Arrays.asList(1, 6, 2, 4, 3));
        for (int i = 0; i < N; i++) {
            arr.set(i, -arr.get(i));
        }
        System.out.println(longestIncreasingSubsequence(arr, N));
    }
}
C#
using System;
using System.Collections.Generic;

public class LIS
{
    // To search for the correct position of num in the array dp
    static int Search(List<int> dp, int num)
    {
        // Initialize low, high, and ans
        int low = 0, high = dp.Count - 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;
    }

    static int LongestIncreasingSubsequence(List<int> arr, int N)
    {
        List<int> ans = new List<int>();

        // Initialize the answer list with the first element of nums
        ans.Add(arr[0]);

        for (int i = 1; i < N; i++)
        {
            if (arr[i] > ans[ans.Count - 1])
            {
                // If the current number is greater than the last element of the answer
                // list, it means we have found a longer increasing subsequence.
                // Hence, we append the current number to the answer list.
                ans.Add(arr[i]);
            }
            else
            {
                // If the current number is not greater than the last element of
                // the answer list, we perform a binary search to find the smallest
                // element in the answer list that is greater than or equal to the
                // current number.

                // The BinarySearch method returns the index of the first element that
                // is not less than the current number.
                int index = ans.BinarySearch(arr[i]);
                if (index < 0)
                    index = ~index; // If not found, BinarySearch returns bitwise complement of the index to insert

                // We update the element at the found position with the current number.
                // By doing this, we are maintaining a sorted order in the answer list.
                ans[index] = arr[i];
            }
        }

        // The length of the answer list represents the length of the
        // longest increasing subsequence.
        return ans.Count;
    }

    // Driver code
    public static void Main(string[] args)
    {
        int N = 5;
        List<int> arr = new List<int> { 1, 6, 2, 4, 3 };
        for (int i = 0; i < N; i++)
            arr[i] = -arr[i]; // Negating the array elements to find the longest decreasing subsequence

        Console.WriteLine(LongestIncreasingSubsequence(arr, N));
    }
}
Javascript
// Function to search for the correct position of num in the array dp using binary search
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) {
            // If mid element is >= num, search for the left half
            ans = mid;
            high = mid - 1;
        } else {
            // If mid element is < num, search for the right half
            low = mid + 1;
        }
    }
    return ans;
}

// Function to find the length of the longest increasing subsequence
function longestIncreasingSubsequence(arr, N) {
    let ans = [];

    // Initialize the answer array with the first element of arr
    ans.push(arr[0]);

    for (let i = 1; i < N; i++) {
        if (arr[i] > ans[ans.length - 1]) {
            // If the current number is greater than the last element of the answer array,
            // it means we have found a longer increasing subsequence.
            // Hence, we append the current number to the answer array.
            ans.push(arr[i]);
        } else {
            // If the current number is not greater than the last element of the answer array,
            // perform a binary search to find the smallest element in the answer array
            // that is greater than or equal to the current number.
            let low = ans.findIndex(el => el >= arr[i]);
            if (low < 0) {
                low = -(low + 1);
            }
            // Update the element at the found position with the current number.
            // By doing this, we are maintaining a sorted order in the answer array.
            ans[low] = arr[i];
        }
    }

    // The length of the answer array represents the length of the longest increasing subsequence.
    return ans.length;
}

// Driver code
const N = 5;
let arr = [1, 6, 2, 4, 3];
arr = arr.map(num => -num); // Negating elements of the array
console.log(longestIncreasingSubsequence(arr, N));
Python3
import bisect
def longestIncreasingSubsequence(arr):
    ans = []

    # Initialize the answer list with the
    # first element of arr
    ans.append(arr[0])

    # Traverse through the array starting from
    # the second element
    for i in range(1, len(arr)):
        if arr[i] > ans[-1]:
            # If the current number is greater
            # than the last element of the answer
            # list, it means we have found a
            # longer increasing subsequence.
            # Hence, we append the current number
            # to the answer list.
            ans.append(arr[i])
        else:
            # If the current number is not
            # greater than the last element of
            # the answer list, we perform
            # a binary search to find the smallest
            # element in the answer list that
            # is greater than or equal to the
            # current number.

            # The bisect.bisect_left() function
            # returns the index where the current
            # number should be inserted in order
            # to maintain the sorted order.
            low = bisect.bisect_left(ans, arr[i])

            # We update the element at the
            # found position with the current number.
            # By doing this, we are maintaining
            # a sorted order in the answer list.
            ans[low] = arr[i]

    # The length of the answer list
    # represents the length of the
    # longest increasing subsequence.
    return len(ans)


# Driver code
if __name__ == "__main__":
    arr = [-1, -6, -2, -4, -3]
    print(longestIncreasingSubsequence(arr))

Output
3







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



Similar Reads

Divide given numeric string into at most two increasing subsequences which form an increasing string upon concatenation
Given a string S consisting of N digits, the task is to partition the string into at most two increasing subsequences such that concatenation of them also forms an increasing string. If it is not possible to do so, then print "-1". Examples: Input: S = “040425524644”Output: 0022444 44556Explanation:One of the possible way to partition the given str
10 min read
Count the number of contiguous increasing and decreasing subsequences in a sequence
For a given distinct integer sequence of size N, the task is to count the number of contiguous increasing subsequence and contiguous decreasing subsequence in this sequence.Examples: Input: arr[] = { 80, 50, 60, 70, 40 } Output: 1 2 Explanation: The only one increasing subsequence is (50, 60, 70) and two decreasing subsequences are (80, 50) and (70
9 min read
Number of Longest Increasing Subsequences
Given an array arr[] of size N, the task is to count the number of longest increasing subsequences present in the given array. Examples: Input: arr[] = {2, 2, 2, 2, 2}Output: 5Explanation: The length of the longest increasing subsequence is 1, i.e. {2}. Therefore, count of longest increasing subsequences of length 1 is 5. Input: arr[] = {1, 3, 5, 4
21 min read
Minimize the number of strictly increasing subsequences in an array | Set 2
Given an array arr[] of size N, the task is to print the minimum possible count of strictly increasing subsequences present in the array. Note: It is possible to swap the pairs of array elements. Examples: Input: arr[] = {2, 1, 2, 1, 4, 3}Output: 2Explanation: Sorting the array modifies the array to arr[] = {1, 1, 2, 2, 3, 4}. Two possible increasi
6 min read
Count number of increasing subsequences of size k
Given an array arr[] containing n integers. The problem is to count number of increasing subsequences in the array of size k. Examples: Input : arr[] = {2, 6, 4, 5, 7}, k = 3Output : 5The subsequences of size '3' are:{2, 6, 7}, {2, 4, 5}, {2, 4, 7},{2, 5, 7} and {4, 5, 7}.Input : arr[] = {12, 8, 11, 13, 10, 15, 14, 16, 20}, k = 4Output : 39Approach
23 min read
Print all subsequences in first decreasing then increasing by selecting N/2 elements from [1, N]
Given a positive integer N, the task is to print all the subsequences of the array in such a way that the subsequence is first decreasing then increasing by selecting ceil(N/2) elements from 1 to N. Examples: Input: N = 5Output :(2, 1, 3), (2, 1, 4), (2, 1, 5), (3, 1, 2), (3, 1, 4), (3, 1, 5), (3, 2, 4), (3, 2, 5), (4, 1, 2), (4, 1, 3), (4, 1, 5),
11 min read
Check if given Array can be divided into subsequences of K increasing consecutive integers
Given an array arr[] of N integers and a positive integer K, the task is to check if it is possible to divide the array into increasing subsequences of K consecutive integers such each element can contribute in only a single subsequence. Example: Input: arr[] = {1, 2, 1, 3, 2, 3}, K = 3Output: YesExplanation: The given array can be divided as {1, 2
11 min read
Length of Longest Increasing Subsequences (LIS) using Segment Tree
Given an array arr[] of size N, the task is to count the number of longest increasing subsequences present in the given array. Example: Input: arr[] = {2, 2, 2, 2, 2}Output: 5Explanation: The length of the longest increasing subsequence is 1, i.e. {2}. Therefore, count of longest increasing subsequences of length 1 is 5. Input: arr[] = {1, 3, 5, 4,
18 min read
Count all increasing subsequences
We are given an array of digits (values lie in range from 0 to 9). The task is to count all the sub sequences possible in array such that in each subsequence every digit is greater than its previous digits in the subsequence. Examples: Input : arr[] = {1, 2, 3, 4}Output: 15Explanation: There are 15 increasing subsequences {1}, {2}, {3}, {4}, {1,2},
8 min read
Number of K length subsequences with minimum sum
Given an array arr[] of size N and an integer K, the task is to find the number of K length subsequences of this array such that the sum of these subsequences is the minimum possible. Examples: Input: arr[] = {1, 2, 3, 4}, K = 2 Output: 1 Subsequences of length 2 are (1, 2), (1, 3), (1, 4), (2, 3), (2, 4) and (3, 4). The minimum sum is 3 and the on
8 min read