📜  最小递增子序列数

📅  最后修改于: 2021-09-22 10:28:52             🧑  作者: 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