📜  最长递增的子序列,在数组的排序表示形式中形成子数组

📅  最后修改于: 2021-05-14 07:24:23             🧑  作者: Mango

给定N个整数的数组arr [] ,任务是找到最长递增子序列的长度,以便在对原始数组进行排序时形成一个子数组。

例子:

天真的方法:想法是生成数组的所有可能的子序列,然后在对原始数组进行排序时检查其中哪一个形成最长的子数组。

时间复杂度: O(2 N )
辅助空间: O(N)

高效方法:想法是使用动态编程方法来解决此问题。步骤如下:

  1. 将每个元素的频率存储在Map中的给定数组中。
  2. 将原始数组存储在一个临时数组中,并对给定的数组进行排序。
  3. 初始化大小为N * 3的2D数组,其中:
    • dp [N] [i]将存储数字X直到位置i
    • dp [x] [1]将存储数字X的计数+数字(X – 1)的计数,直到位置i为止。
    • dp [x] [2]将存储序列的实际长度,直到位置i为止。
  4. 遍历原始数组,并在原始数组中的每个索引i上,仅在所有(X – 1)个元素已包含在子序列中时才在当前位置i包含该元素,并更新dp [] []和在此状态之后,更新最大子序列大小。
  5. 完成上述步骤后,打印最大子序列大小。

下面是上述方法的实现:

C++
// C++ program to implement
// the above approach
 
#include 
using namespace std;
 
// Function to find the length of the
// longest increasing sorted sequence
int LongestSequence(int a[], int n)
{
    // Stores the count of all elements
    map m;
 
    int ar[n + 1], i, j;
 
    // Store the original array
    for (i = 1; i <= n; i++) {
        ar[i] = a[i - 1];
    }
 
    // Sort the array
    sort(a, a + n);
 
    int c = 1;
    m[a[0]] = c;
 
    for (i = 1; i <= n; i++) {
 
        // If adjacent element
        // are not same
        if (a[i] != a[i - 1]) {
 
            // Increment count
            c++;
            m[a[i]] = c;
        }
    }
 
    // Store frequency of each element
    map cnt;
 
    // Initialize a DP array
    int dp[n + 1][3] = { 0 };
    cnt[0] = 0;
 
    // Iterate over the array ar[]
    for (i = 1; i <= n; i++) {
        ar[i] = m[ar[i]];
        cnt[ar[i]]++;
    }
 
    // Length of the longest
    // increasing sorted sequence
    int ans = 0, x;
 
    // Iterate over the array
    for (i = 1; i <= n; i++) {
 
        // Current element
        x = ar[i];
 
        // If the element has been
        // encountered the first time
        if (dp[x][0] == 0) {
 
            // If all the x - 1 previous
            // elements have already appeared
            if (dp[x - 1][0] == cnt[x - 1]) {
                dp[x][1] = dp[x - 1][1];
                dp[x][2] = dp[x - 1][1];
            }
 
            // Otherwise
            else {
                dp[x][1] = dp[x - 1][0];
            }
        }
 
        dp[x][2] = max(dp[x - 1][0],
                       dp[x][2]);
 
        if (dp[x - 1][0] == cnt[x - 1]) {
 
            // If all x-1 elements have
            // already been encountered
            dp[x][2] = max(dp[x][2],
                           dp[x - 1][1]);
        }
        for (j = 0; j < 3; j++) {
 
            // Increment the count of
            // the current element
            dp[x][j]++;
 
            // Update maximum
            // subsequence size
            ans = max(ans, dp[x][j]);
        }
    }
 
    // Return the maximum
    // subsequence size
    return ans;
}
 
// Driver Code
int main()
{
    int arr[] = { 2, 6, 4, 8, 2, 9 };
 
    int N = sizeof(arr) / sizeof(arr[0]);
 
    // Function Call
    cout << LongestSequence(arr, N);
    return 0;
}


Java
// Java program to implement
// the above approach
import java.io.*;
import java.util.*;
 
class GFG{
     
// Function to find the length of the
// longest increasing sorted sequence
static int LongestSequence(int a[], int n)
{
     
    // Stores the count of all elements
    HashMap m = new HashMap<>();
     
    int ar[] = new int[n + 1];
    int i = 0;
    int j = 0;
 
    // Store the original array
    for(i = 1; i <= n; i++)
    {
        ar[i] = a[i - 1];
    }
 
    // Sort the array
    Arrays.sort(a);
     
    int c = 1;
    m.put(a[0], c);
 
    for(i = 1; i < n; i++)
    {
         
        // If adjacent element
        // are not same
        if (a[i] != a[i - 1])
        {
             
            // Increment count
            c++;
            m.put(a[i], c);
        }
    }
 
    // Store frequency of each element
    HashMap cnt = new HashMap<>();
     
    // Initialize a DP array
    int dp[][] = new int[n + 1][3];
 
    cnt.put(0, 0);
 
    // Iterate over the array ar[]
    for(i = 1; i <= n; i++)
    {
        ar[i] = m.get(ar[i]);
         
        if (cnt.containsKey(ar[i]))
            cnt.put(ar[i], cnt.get(ar[i]) + 1);
        else
            cnt.put(ar[i], 1);
    }
 
    // Length of the longest
    // increasing sorted sequence
    int ans = 0, x;
 
    // Iterate over the array
    for(i = 1; i <= n; i++)
    {
         
        // Current element
        x = ar[i];
 
        // If the element has been
        // encountered the first time
        if (dp[x][0] == 0)
        {
             
            // If all the x - 1 previous
            // elements have already appeared
            if (dp[x - 1][0] == cnt.get(x - 1))
            {
                dp[x][1] = dp[x - 1][1];
                dp[x][2] = dp[x - 1][1];
            }
 
            // Otherwise
            else
            {
                dp[x][1] = dp[x - 1][0];
            }
        }
         
        dp[x][2] = Math.max(dp[x - 1][0],
                            dp[x][2]);
 
        if (dp[x - 1][0] == cnt.get(x - 1))
        {
             
            // If all x-1 elements have
            // already been encountered
            dp[x][2] = Math.max(dp[x][2],
                                dp[x - 1][1]);
        }
        for(j = 0; j < 3; j++)
        {
 
            // Increment the count of
            // the current element
            dp[x][j]++;
 
            // Update maximum
            // subsequence size
            ans = Math.max(ans, dp[x][j]);
        }
    }
     
    // Return the maximum
    // subsequence size
    return ans;
}
 
// Driver code
public static void main(String[] args)
{
    int arr[] = { 2, 6, 4, 8, 2, 9 };
    int n = arr.length;
     
    System.out.println(LongestSequence(arr, n));
}
}
 
// This code is contributed by bikram2001jha


Python3
# Python 3 program to implement
# the above approach
 
# Function to find the length of the
# longest increasing sorted sequence
def LongestSequence(a, n):
   
  # Stores the count of all elements
  m = {i : 0 for i in range(100)}
 
  ar = [0 for i in range(n + 1)]
 
  # Store the original array
  for i in range(1, n + 1):
    ar[i] = a[i - 1]
 
  # Sort the array
  a.sort(reverse = False)
 
  c = 1
  m[a[0]] = c
 
  for i in range(1, n):
     
    # If adjacent element
    # are not same
    if (a[i] != a[i - 1]):
       
      # Increment count
      c += 1
      m[a[i]] = c
 
  # Store frequency of each element
  cnt = {i : 0 for i in range(100)}
 
  # Initialize a DP array
  dp = [[0 for i in range(3)]
           for j in range(n + 1)]
   
  cnt[0] = 0
 
  # Iterate over the array ar[]
  for i in range(1, n + 1):
     
    ar[i] = m[ar[i]]
    cnt[ar[i]] += 1
 
  # Length of the longest
  # increasing sorted sequence
  ans = 0
 
  # Iterate over the array
  for i in range(1, n + 1):
     
    # Current element
    x = ar[i]
 
    # If the element has been
    # encountered the first time
    if (dp[x][0] == 0):
       
      # If all the x - 1 previous
      # elements have already appeared
      if (dp[x - 1][0] == cnt[x - 1]):
        dp[x][1] = dp[x - 1][1]
        dp[x][2] = dp[x - 1][1]
 
      # Otherwise
      else:
        dp[x][1] = dp[x - 1][0]
 
      dp[x][2] = max(dp[x - 1][0], dp[x][2])
 
      if (dp[x - 1][0] == cnt[x - 1]):
         
        # If all x-1 elements have
        # already been encountered
        dp[x][2] = max(dp[x][2], dp[x - 1][1])
         
      for j in range(3):
         
        # Increment the count of
        # the current element
        dp[x][j] += 1
 
        # Update maximum
        # subsequence size
        ans = max(ans, dp[x][j])
 
  # Return the maximum
  # subsequence size
  return ans
 
# Driver Code
if __name__ == '__main__':
   
  arr =  [ 2, 6, 4, 8, 2, 9 ]
 
  N = len(arr)
 
  # Function call
  print(LongestSequence(arr, N))
   
# This code is contributed by SURENDRA_GANGWAR


C#
// C# program to implement
// the above approach
using System.Collections.Generic;
using System;
 
class GFG{
     
// Function to find the length of the
// longest increasing sorted sequence
static int LongestSequence(int []a, int n)
{
     
    // Stores the count of all elements
    Dictionary m = new Dictionary();
                                        
    int []ar = new int[n + 1];
    int i = 0;
    int j = 0;
 
    // Store the original array
    for(i = 1; i <= n; i++)
    {
        ar[i] = a[i - 1];
    }
 
    // Sort the array
    Array.Sort(a);
     
    int c = 1;
    m[a[0]]= c;
 
    for(i = 1; i < n; i++)
    {
         
        // If adjacent element
        // are not same
        if (a[i] != a[i - 1])
        {
             
            // Increment count
            c++;
            m[a[i]]= c;
        }
    }
 
    // Store frequency of each element
    Dictionarycnt = new Dictionary();
     
    // Initialize a DP array
    int [,]dp = new int[n + 1, 3];
 
    cnt[0] = 0;
 
    // Iterate over the array ar[]
    for(i = 1; i <= n; i++)
    {
        ar[i] = m[ar[i]];
         
        if (cnt.ContainsKey(ar[i]))
            cnt[ar[i]]= cnt[ar[i]] + 1;
        else
            cnt[ar[i]]= 1;
    }
 
    // Length of the longest
    // increasing sorted sequence
    int ans = 0, x;
 
    // Iterate over the array
    for(i = 1; i <= n; i++)
    {
         
        // Current element
        x = ar[i];
 
        // If the element has been
        // encountered the first time
        if (dp[x, 0] == 0)
        {
             
            // If all the x - 1 previous
            // elements have already appeared
            if (dp[x - 1, 0] == cnt[x - 1])
            {
                dp[x, 1] = dp[x - 1, 1];
                dp[x, 2] = dp[x - 1, 1];
            }
 
            // Otherwise
            else
            {
                dp[x, 1] = dp[x - 1, 0];
            }
        }
         
        dp[x, 2] = Math.Max(dp[x - 1, 0],
                            dp[x, 2]);
 
        if (dp[x - 1, 0] == cnt[x - 1])
        {
             
            // If all x-1 elements have
            // already been encountered
            dp[x, 2] = Math.Max(dp[x, 2],
                                dp[x - 1, 1]);
        }
        for(j = 0; j < 3; j++)
        {
 
            // Increment the count of
            // the current element
            dp[x, j]++;
 
            // Update maximum
            // subsequence size
            ans = Math.Max(ans, dp[x, j]);
        }
    }
     
    // Return the maximum
    // subsequence size
    return ans;
}
 
// Driver code
public static void Main()
{
    int []arr = { 2, 6, 4, 8, 2, 9 };
    int n = arr.Length;
     
    Console.WriteLine(LongestSequence(arr, n));
}
}
 
// This code is contributed by Stream_Cipher


输出:
3


时间复杂度: O(N)
辅助空间: O(N)