2011-01-24 16 views
5

Dada la siguiente pregunta no decreciente,Encuentra más larga secuencia

Dada una matriz de enteros A de longitud n, encontrar la secuencia más larga {i_1, ..., i_k} tal que i_j < i_ (j + 1) y A [i_j] < = A [i_ (j + 1)] para cualquier j en [1, k-1].

Aquí está mi solución, ¿es esto correcto?

max_start = 0; // store the final result 
max_end = 0; 
try_start = 0; // store the initial result 
try_end = 0; 

FOR i=0; i<(A.length-1); i++ DO 
    if A[i] <= A[i+1] 
    try_end = i+1; // satisfy the condition so move the ending point 
    else    // now the condition is broken 
    if (try_end - try_start) > (max_end - max_start) // keep it if it is the maximum 
     max_end = try_end; 
     max_start = try_start; 
    endif 
    try_start = i+1; // reset the search 
    try_end = i+1; 
    endif 
ENDFOR 

// Checking the boundary conditions based on comments by Jason 
if (try_end - try_start) > (max_end - max_start) 
    max_end = try_end; 
    max_start = try_start; 
endif 

De alguna manera, no creo que esta es una solución correcta, pero no puedo encontrar un contraejemplo que desaprueba esta solución.

¿alguien puede ayudar?

Gracias

+1

Me parece bastante bueno. ¿Puedes darme una idea de por qué crees que es incorrecto? –

Respuesta

5

No veo ningún retroceso en su algoritmo, y parece ser adecuado para bloques contiguos de números no decrecientes. Si he entendido bien, por la siguiente entrada:

1 2 3 4 10 5 6 7 

su algoritmo volvería 1 2 3 4 10 en lugar de 1 2 3 4 5 6 7.

Intente encontrar una solución usando dynamic programming.

+0

Creo que esto es lo que estoy buscando. Como mencionaste, la pregunta original no enfatiza que la secuencia debe ser continua. -thx – q0987

2

Te estás perdiendo el caso de que la condición no se ha roto en su última iteración:

1, 3, 5, 2, 4, 6, 8, 10 

Nunca promover try_start y try_end-max_start y max_end a menos que su condición es roto. Debe realizar la misma verificación al final del ciclo.

+0

Creo que es un comentario similar, pero para una lista de longitud 1, esto no se ejecuta en el ciclo, así que obtienes 0 y 0 para comenzar y terminar – vmpstr

+0

He hecho una corrección para mi solución en función de tu sugerencia. Sin embargo, mi preocupación es que mi solución es fundamentalmente errónea dada la pregunta original porque la solución proporcionada en el libro utiliza un DP bastante complicado para resolverlo. Creo que extraño información clave de la pregunta. -thx – q0987

+0

ah - Eché de menos el aspecto de contigüidad. ¡buena suerte! –

1

Bueno, parece que estás encontrando el inicio y el final de la secuencia, que puede ser correcto pero no fue lo que se pidió. Comenzaría leyendo http://en.wikipedia.org/wiki/Longest_increasing_subsequence - Creo que esta es la pregunta que se hizo y es un problema bastante conocido. En general, no se puede resolver en tiempo lineal, y también requerirá alguna forma de programación dinámica. (También hay una variante n^2 más fácil del algoritmo en Wikipedia - solo haga un barrido lineal en lugar de la búsqueda binaria.)

-1
#include <algorithm> 
#include <vector> 
#include <stdio.h> 
#include <string.h> 
#include <assert.h> 

template<class RandIter> 
class CompM { 
    const RandIter X; 
    typedef typename std::iterator_traits<RandIter>::value_type value_type; 
    struct elem { 
     value_type c; // char type 
     explicit elem(value_type c) : c(c) {} 
    }; 
public: 
    elem operator()(value_type c) const { return elem(c); } 
    bool operator()(int a, int b) const { return X[a] < X[b]; } // for is_sorted 
    bool operator()(int a, elem b) const { return X[a] < b.c; } // for find 
    bool operator()(elem a, int b) const { return a.c < X[b]; } // for find 
    explicit CompM(const RandIter X) : X(X) {} 
}; 

template<class RandContainer, class Key, class Compare> 
int upper(const RandContainer& a, int n, const Key& k, const Compare& comp) { 
    return std::upper_bound(a.begin(), a.begin() + n, k, comp) - a.begin(); 
} 

template<class RandIter> 
std::pair<int,int> lis2(RandIter X, std::vector<int>& P) 
{ 
    int n = P.size(); assert(n > 0); 
    std::vector<int> M(n); 
    CompM<RandIter> comp(X); 
    int L = 0; 
    for (int i = 0; i < n; ++i) { 
     int j = upper(M, L, comp(X[i]), comp); 
     P[i] = (j > 0) ? M[j-1] : -1; 
     if (j == L) L++; 
     M[j] = i; 
    } 
    return std::pair<int,int>(L, M[L-1]); 
} 

int main(int argc, char** argv) 
{ 
    if (argc < 2) { 
     fprintf(stderr, "usage: %s string\n", argv[0]); 
     return 3; 
    } 
    const char* X = argv[1]; 
    int n = strlen(X); 
    if (n == 0) { 
     fprintf(stderr, "param string must not empty\n"); 
     return 3; 
    } 
    std::vector<int> P(n), S(n), F(n); 
    std::pair<int,int> lt = lis2(X, P); // L and tail 
    int L = lt.first; 
    printf("Longest_increasing_subsequence:L=%d\n", L); 
    for (int i = lt.second; i >= 0; --i) { 
     if (!F[i]) { 
      int j, k = 0; 
      for (j = i; j != -1; j = P[j], ++k) { 
       S[k] = j; 
       F[j] = 1; 
      } 
      std::reverse(S.begin(), S.begin()+k); 
      for (j = 0; j < k; ++j) 
       printf("%c", X[S[j]]); 
      printf("\n"); 
     } 
    } 
    return 0; 
} 
+1

Por favor, explique su código en lugar de simplemente publicarlo de la manera en que esto. –

Cuestiones relacionadas