📜  最小递增子序列数

📅  最后修改于: 2021-04-27 22:43:49             🧑  作者: Mango

给定大小为N的整数数组,您必须将其划分为最小数量的“严格增加的子序列”
例如:假设序列为{1、3、2、4},则答案为2。在这种情况下,第一个递增序列为{1、3、4},第二个为{2}。
例子:

如果我们关注示例,则可以看到最小递增子序列数等于最长递减子序列的长度,其中最长递减子序列中的每个元素代表一个递增子序列,因此可以在N * Log(N)时间中找到复杂度与最长递增子序列相同(通过将所有元素乘以-1)。
我们遍历所有元素,并在排序数组(多集)S中存储到目前为止找到的每个递增子序列中的最后一个元素,并且对于每个元素X,我们都使用S中的二进制搜索-选择小于X的最大元素-并用X替换它,这意味着我们将当前元素添加到以X结尾的递增子序列中;否则,如果S中不存在小于X的元素,则将其插入S中,形成新的递增子序列,依此类推直到最后一个元素而我们最后的答案将是S的大小。

CPP
// C++ program to count the Minimum number of
// increasing subsequences
#include 
using namespace std;
 
int MinimumNumIncreasingSubsequences(int arr[], int n)
{
    multiset 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::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 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 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));
    }
}


输出
Minimum number of increasing subsequences are : 3

时间复杂度:O(N log(N))
辅助空间:O(N)
方法2 :的想法是找到最长的递减子序列

  • 初始化长度为n的dp数组。
  • 反转数组的所有元素。
  • 对于数组中的每个元素。
  • 如果dp数组中的当前元素找到索引。
  • 找到有效的最大索引。
  • dp [i]表示以长度i子序列结尾的最小元素。

下面是上述方法的实现

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 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));
    }
}
输出
1