Maximizar la longitud de la subsecuencia principal creciente más larga de la array dada

Dada una array, arr[] de tamaño N , la tarea es encontrar la longitud de la subsecuencia principal creciente más larga posible realizando las siguientes operaciones.

  • Si arr[i] ya es un número primo , no es necesario actualizar arr[i] .
  • Actualice arr[i] no primo al número primo más cercano menor que arr[i] .
  • Actualice arr[i] no primo al número primo más cercano mayor que arr[i] .

Ejemplos:

Entrada: arr[] = {8, 6, 9, 2, 5}
Salida: 2
Explicación :
las posibles reorganizaciones de la array son: {{7, 5, 2, 5}, {7, 7, 2, 5}, {11, 5, 2, 5}, {1, 7, 2, 5}}.
Por lo tanto, la longitud de la subsecuencia prima creciente más larga = 2.

Entrada: arr[] = {27, 38, 43, 68, 83, 12, 69, 12}
Salida: 5

Enfoque ingenuo: el enfoque más simple es actualizar todos los elementos de la array dada a su número primo más pequeño más cercano o a su número primo mayor más cercano y luego generar todas las subsecuencias posibles de la array dada e imprimir la longitud de la subsecuencia más larga que consiste en primo números en orden creciente.
Complejidad temporal: O(2 N )
Espacio auxiliar: O(N)

Enfoque eficiente: la idea es utilizar el enfoque de programación dinámica para optimizar el enfoque anterior. Este problema es una variación básica del problema de la subsecuencia principal creciente más larga (LIPS) . Siga los pasos a continuación para resolver el problema.

  1. Inicialice una array bidimensional , digamos dp[][] de tamaño N * 2 , donde dp[i][0] almacena la longitud de la subsecuencia principal creciente más larga eligiendo el número primo más cercano más pequeño que arr[i] en i th index y dp[i][1] almacena la longitud de la subsecuencia prima creciente más larga eligiendo el número primo más cercano mayor o igual que arr[i] en i th index. A continuación se muestra la relación de recurrencia:
    • Si el número primo menor más cercano a arr[j] < el número primo menor más cercano a arr[i]: dp[i][0] = 1 + dp[j][0]
    • Si el número primo más cercano es mayor o igual que arr[j] < el número primo más pequeño más cercano a arr[i]: dp[i][0] = max(dp[i][0], 1 + dp[j][1 ])
    • Si el número primo menor más cercano a arr[j] < el número primo menor más cercano a arr[i]: dp[i][1] = 1 + dp[j][0]
    • Si el número primo mayor o igual más cercano a arr[j] < el número primo más cercano mayor o igual a arr[i]: dp[i][1] = max(dp[i][1], 1 + dp[j] [1])

    Aquí el valor de j = 0, 1, …, (i-1)

  2. Utilice la criba de Eratóstenes para calcular eficientemente los números primos .
  3. Recorra la array arr[] y para cada índice, i , actualice arr[i] al número primo más cercano de arr[i] .
  4. Para cada índice i , encuentre la longitud de la subsecuencia prima creciente más larga que termina en i , de manera óptima.
  5. Finalmente, devuelva la longitud de la subsecuencia prima creciente más larga.

A continuación se muestra la implementación del enfoque anterior:

Java

// Java Program to implement
// the above approach
  
import java.util.*;
  
public class Main {
  
    // Stores the closest prime
    // number for each array element
    static TreeSet<Integer> set
        = new TreeSet<>();
  
    // Function to find the length of longest
    // increasing prime subsequence
    public static int LIPS(int arr[], int N)
    {
        // Base case
        if (arr.length == 0)
            return 0;
  
        int dp[][] = new int[N + 1][2];
  
        // Store the length of the longest
        // increasing prime subsequence
        int max_subsequence = 0;
        for (int i = 0; i < arr.length;
             i++) {
            // Store the length of LIPS
            // by choosing the closest prime
            // number smaller than arr[i]
            dp[i][0] = (arr[i] >= 2) ? 1 : 0;
  
            // Store the length of longest LIPS
            // by choosing the closest prime
            // number greater than arr[i]
            dp[i][1] = 1;
            for (int j = 0; j < i; j++) {
  
                // Store closest smaller
                // prime number
                Integer option1 = set.floor(arr[j]);
  
                // Store closest prime number
                // greater or equal
                Integer option2 = set.ceiling(arr[j]);
  
                // Recurrence relation
  
                // Fill the value of dp[i][0]
                if (option1 != null
                    && option1 < set.floor(arr[i]))
                    dp[i][0]
                        = Math.max(dp[i][0], dp[j][0] + 1);
  
                if (option2 != null
                    && option2 < set.floor(arr[i]))
                    dp[i][0]
                        = Math.max(dp[i][0], dp[j][1] + 1);
  
                // Fill the value of dp[i][1]
                if (option1 != null
                    && option1 < set.ceiling(arr[i]))
                    dp[i][1]
                        = Math.max(dp[i][0], dp[j][0] + 1);
  
                if (option2 != null
                    && option2 < set.ceiling(arr[i]))
                    dp[i][1]
                        = Math.max(dp[i][1], dp[j][1] + 1);
            }
  
            // Store the length of the longest
            // increasing prime subsequence
            max_subsequence
                = Math.max(max_subsequence, dp[i][0]);
  
            max_subsequence
                = Math.max(max_subsequence, dp[i][1]);
        }
  
        return max_subsequence;
    }
  
    // Function to generate all prime numbers
    public static void prime_sieve()
    {
        // Store all prime numbers
        boolean primes[]
            = new boolean[1000000 + 5];
  
        // Consider all prime numbers
        // to be true initially
        Arrays.fill(primes, true);
  
        // Mark 0 and 1 non-prime
        primes[0] = primes[1] = false;
  
        // Set all even numbers to
        // non-prime
        for (int i = 4; i <= 1000000;
             i += 2)
            primes[i] = false;
  
        for (int i = 3; i <= 1000000;
             i += 2) {
  
            // If current element is prime
            if (primes[i]) {
  
                // Update all its multiples
                // as non-prime
                for (int j = 2 * i; j <= 1000000;
                     j += i)
                    primes[j] = false;
            }
        }
  
        // Mark 2 as prime
        set.add(2);
  
        // Add all primes to the set
        for (int i = 3; i <= 1000000;
             i += 2)
            if (primes[i])
                set.add(i);
    }
  
    // Driver Code
    public static void main(String args[])
    {
        int N = 6;
        int arr[] = { 6, 7, 8, 9, 10, 11 };
  
        prime_sieve();
  
        System.out.println(LIPS(arr, N));
    }
}
Producción:

3

Complejidad temporal: O(N 2 logN)
Espacio auxiliar: O(N)

Publicación traducida automáticamente

Artículo escrito por hemanthswarna1506 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *