Open In App

Minimum number of strictly decreasing subsequences

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

Given an array arr[] of size N. The task is to split the array into minimum number of strictly decreasing subsequences. Calculate the minimum number of subsequences we can get by splitting.

Examples:

Input: N = 4, arr[] = {3, 5, 1, 2}
Output: 2
Explanation: We can split the array into two subsequences: {3,1} and {5,2}

Both are strictly decreasing subsequence.

Input: N = 3, arr[] = {3,3,3}
Output: 3
Explanation: We can split the array into three subsequences: {3},{3} and {3}

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

If we observe carefully, we can see that the Minimum number of decreasing subsequences is equal to the length of longest increasing subsequence where each element from the longest increasing subsequence belongs to a single decreasing subsequence, so it can be found in N*Log(N)

Below is the implementation of the above approach:

C++




#include <iostream>
#include <vector>
#include <algorithm>
 
using namespace std;
 
class Solution {
public:
    // Function to find the length of the minimum decreasing subsequence.
    int minDecreasingSub(int N, vector<int> arr) {
        // Initialize a vector to store the elements of the decreasing subsequence.
        vector<int> seq;
         
        // Add the first element of the array to the sequence.
        seq.push_back(arr[0]);
 
        // Iterate through the array starting from the second element.
        for (auto i = 1; i < N; i++) {
            // Find the position where the current element should be inserted in the sequence.
            int ind = upper_bound(seq.begin(), seq.end(), arr[i]) - seq.begin();
 
            // If the position is equal to the size of the sequence, push the element to the end.
            if (ind == seq.size())
                seq.push_back(arr[i]);
            // Otherwise, replace the element at the found position with the current element.
            else
                seq[ind] = arr[i];
        }
 
        // Return the size of the sequence as the result.
        return seq.size();
    }
};
 
int main() {
    // Example usage in the main block
    vector<int> arr = {5, 2, 7, 8, 6};
    int N = arr.size();
 
    Solution solution;
    int result = solution.minDecreasingSub(N, arr);
 
    // Display the result.
    cout << "Length of the minimum decreasing subsequence: " << result << endl;
 
    return 0;
}


Java




import java.util.ArrayList;
import java.util.Collections;
 
class Solution {
    // Function to find the length of the minimum decreasing subsequence.
    public int minDecreasingSub(int N, ArrayList<Integer> arr) {
        // Initialize a list to store the elements of the decreasing subsequence.
        ArrayList<Integer> seq = new ArrayList<>();
 
        // Add the first element of the array to the sequence.
        seq.add(arr.get(0));
 
        // Iterate through the array starting from the second element.
        for (int i = 1; i < N; i++) {
            // Find the position where the current element should be inserted in the sequence.
            int ind = Collections.binarySearch(seq, arr.get(i));
 
            // If the position is negative, it means the element is not present.
            // Convert the negative position to the insertion point.
            ind = (ind < 0) ? -ind - 1 : ind;
 
            // If the position is equal to the size of the sequence, add the element to the end.
            if (ind == seq.size())
                seq.add(arr.get(i));
            // Otherwise, replace the element at the found position with the current element.
            else
                seq.set(ind, arr.get(i));
        }
 
        // Return the size of the sequence as the result.
        return seq.size();
    }
 
    public static void main(String[] args) {
        // Example usage in the main block
        ArrayList<Integer> arr = new ArrayList<>();
        arr.add(5);
        arr.add(2);
        arr.add(7);
        arr.add(8);
        arr.add(6);
        int N = arr.size();
 
        Solution solution = new Solution();
        int result = solution.minDecreasingSub(N, arr);
 
        // Display the result.
        System.out.println("Length of the minimum decreasing subsequence: " + result);
    }
}


Python




class Solution:
    # Function to find the length of the minimum decreasing subsequence.
    def min_decreasing_sub(self, N, arr):
        # Initialize a list to store the elements of the decreasing subsequence.
        seq = [arr[0]]
 
        # Iterate through the array starting from the second element.
        for i in range(1, N):
            # Find the position where the current element should be inserted in the sequence.
            ind = self.binary_search(seq, arr[i])
 
            # If the position is equal to the size of the sequence, add the element to the end.
            if ind == len(seq):
                seq.append(arr[i])
            # Otherwise, replace the element at the found position with the current element.
            else:
                seq[ind] = arr[i]
 
        # Return the size of the sequence as the result.
        return len(seq)
 
    # Custom binary search function
    def binary_search(self, seq, target):
        low, high = 0, len(seq)
 
        while low < high:
            mid = (low + high) // 2
 
            if seq[mid] < target:
                low = mid + 1
            else:
                high = mid
 
        return low
 
# Example usage
arr = [5, 2, 7, 8, 6]
N = len(arr)
 
solution = Solution()
result = solution.min_decreasing_sub(N, arr)
 
# Display the result.
print("Length of the minimum decreasing subsequence:", result)


C#




using System;
 
class Solution {
    // Function to find the length of the minimum decreasing
    // subsequence.
    public int MinDecreasingSub(int N, int[] arr)
    {
        // Initialize a list to store the elements of the
        // decreasing subsequence.
        int[] seq = new int[] { arr[0] };
 
        // Iterate through the array starting from the
        // second element.
        for (int i = 1; i < N; i++) {
            // Find the position where the current element
            // should be inserted in the sequence.
            int ind = BinarySearch(seq, arr[i]);
 
            // If the position is equal to the size of the
            // sequence, add the element to the end.
            if (ind == seq.Length) {
                Array.Resize(ref seq, seq.Length + 1);
                seq[ind] = arr[i];
            }
            // Otherwise, replace the element at the found
            // position with the current element.
            else {
                seq[ind] = arr[i];
            }
        }
 
        // Return the size of the sequence as the result.
        return seq.Length;
    }
 
    // Custom binary search function
    private int BinarySearch(int[] seq, int target)
    {
        int low = 0, high = seq.Length;
 
        while (low < high) {
            int mid = (low + high) / 2;
 
            if (seq[mid] < target) {
                low = mid + 1;
            }
            else {
                high = mid;
            }
        }
 
        return low;
    }
}
 
class Program {
    static void Main()
    {
        int[] arr = { 5, 2, 7, 8, 6 };
        int N = arr.Length;
 
        Solution solution = new Solution();
        int result = solution.MinDecreasingSub(N, arr);
 
        // Display the result.
        Console.WriteLine(
            "Length of the minimum decreasing subsequence: "
            + result);
    }
}
 
// This code is contributed by shivamgupta0987654321


Javascript




class Solution {
    // Function to find the length of the minimum decreasing subsequence.
    minDecreasingSub(N, arr) {
        // Initialize a sequence array to store the elements of the decreasing subsequence.
        let seq = [];
         
        // Add the first element of the array to the sequence.
        seq.push(arr[0]);
 
        // Iterate through the array starting from the second element.
        for (let i = 1; i < N; i++) {
            // Find the position where the current element should be inserted in the sequence.
            let ind = this.upperBound(seq, arr[i]);
 
            // If the position is equal to the size of the sequence, push the element to the end.
            if (ind === seq.length)
                seq.push(arr[i]);
            // Otherwise, replace the element at the found position with the current element.
            else
                seq[ind] = arr[i];
        }
 
        // Return the size of the sequence as the result.
        return seq.length;
    }
 
    // Helper function to find the upper bound of an element in the sequence.
    upperBound(seq, target) {
        let left = 0;
        let right = seq.length;
 
        while (left < right) {
            let mid = Math.floor((left + right) / 2);
 
            if (seq[mid] <= target) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
 
        return left;
    }
}
 
// Example usage in the main block
let arr = [5, 2, 7, 8, 6];
let N = arr.length;
 
let solution = new Solution();
let result = solution.minDecreasingSub(N, arr);
 
// Display the result.
console.log("Length of the minimum decreasing subsequence: " + result);


Output

Length of the minimum decreasing subsequence: 3



Time Complexity: O(N log N), where N is the length of array arr[].
Auxiliary Space: O(N)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads