2012-02-26 19 views
6

¿Cuál será la peor complejidad para ordenar cadenas de n que tengan n caracteres cada una? ¿Será solo n veces su promedio? caso O(n log n) o algo más ...?Clasificación de cadenas usando Combinar Ordenar

+0

¿De qué estás hablando aquí? – uday

+0

No está claro lo que estás preguntando. –

+0

editado mi pregunta ..... – Abhishek

Respuesta

3

Como @orangeoctopus, utilizando el algoritmo de clasificación estándar en una colección de n cadenas de tamaño n dará como resultado O(n^2 * logn) cálculo.

Sin embargo - Tenga en cuenta que puede hacerlo en O(n^2), con variaciones en radix sort.

La forma más sencilla de hacerlo [en mi opinión] - es

  1. construir un trie, y rellenarla con todas sus cadenas. Entrando cada cadena es O(n) y lo haces n veces - total de O(n^2)
  2. hacer un DFS en el trie, cada vez que se encuentra con la marca de final de cadena - añadirlo a la colección ordenada. El orden de las cadenas añadidas de esta manera es lexicográficamente, por lo que su lista se ordenará lexicográficamente cuando haya terminado.

Es fácil ver que no se puede hacer nada mejor que O(n^2), ya que sólo la lectura de los datos es O(n^2), por tanto, esta solución es óptima en términos de gran O notación de la complejidad del tiempo.

+0

Creo que en lugar de decir "DFS", decir "pre-order transversal" sería más claro. – CEGRD

+0

¿Se puede 'O (n^2)' sin usar trie también? – Kshitij

+0

@Kshitij Sí, haga una ordenación de radix en la cadena, el trie es solo una sugerencia - una clasificación de radix estándar funcionará aquí - usando caracteres (o su representación de bit) cada iteración para lograr el orden parcial actual, hasta agotar todos los bits /caracteres. Esto tomará 'O (n^2)' también. – amit

6

Cuando habla de la notación O con dos elementos con diferentes longitudes, normalmente desea utilizar variables diferentes, como M y N.

lo tanto, si la combinación de una especie es O(N log N), donde N es el número de cadenas ... y la comparación de dos cadenas es O(M) donde M escalas con la longitud de la cadena, y se le dejó con:

O(N log N) * O(M) 

o

O(M N log N) 

donde M es la longitud de la cadena y N es el número de cadenas. Desea utilizar etiquetas diferentes porque no significan lo mismo.

En el extraño caso en el que la longitud media de cadena de escala con el número de cadenas, como si tuviera una matriz almacenada en cadenas o algo por el estilo, se podría argumentar que M = N, y entonces tendría O(N^2 log N)

+0

¿No quiere decir "O (M) donde M ..." en lugar de "O (N) donde N ..."? Y aunque es el peor de los casos, como se solicitó, se debe tener en cuenta que el rendimiento medio de un caso para comparar dos cadenas es O (1), ya que se vuelve geométricamente menos y menos probable que deba visitar cada carácter adicional en las cadenas. – xan

+0

Claro, me refería a ellos por separado, pero lo cambié para usar 'M' para ser más claro. Está pidiendo la "peor complejidad", pero dando un tamaño de aguijón "promedio" ... así que sigue siendo O (N), ¿verdad? –

+0

Sí, la pregunta es un poco confusa con su mezcla de peor y promedio. Creo que tu respuesta sería más fuerte para cubrir ambos. – xan

0

Ordenar n elementos con MergeSort requiere O(N LogN) comparaciones. Si el tiempo para comparar dos elementos es O(1), el tiempo total de ejecución será O(N logN). Sin embargo, la comparación de dos cadenas de longitud N requiere O(N) de tiempo, por lo que una implementación ingenua podría quedarse atascada con el tiempo O(N*N logN).

Esto parece un desperdicio porque no estamos aprovechando el hecho de que solo hay N cadenas para hacer comparaciones. De alguna manera, podemos preprocesar las cadenas para que las comparaciones tomen menos tiempo en promedio.

Aquí hay una idea. Crea una estructura Trie y pon N cadenas allí. El trie tendrá O(N*N) nodos y requerirá O(N*N) tiempo para compilar. Atraviese el árbol y coloque un "ranking" entero a cada nodo en el árbol; Si R (N1) < R (N2), la cadena asociada con el Nodo1 aparece antes que la cadena asociada con el Nodo2 en un diccionario.

Ahora proceda con Mergesort, haga las comparaciones en tiempo O(1) mirando el Trie. El tiempo total de ejecución será O(N*N + N*logN) = O(N*N)

Editar: Mi respuesta es muy similar a la de @amit. Sin embargo procedo con mergesort donde procede con radixsort después del paso de construcción trie.

+0

¿Mantiene también un índice de palabras de mapeo en los nodos trie para que pueda acceder a esos rankings durante el tipo de fusión? aclaración por favor. Además, creo que también debe incluir el costo de atravesar. Entonces, la complejidad debe ser O (N * N + N * N + N * logN). Si esto es cierto, entonces el enfoque de clasificación de radix parece mejor ya que es O (N * N + N * N). – CEGRD

+0

@CERGD: la notación Big O solo trata sobre el crecimiento asintótico con respecto al tamaño de entrada; no trata con factores constantes, O (2 * N * N + NlogN) = O (N * N). Revisando la pregunta después de algunos meses, está claro que la respuesta de amit es más simple y más rápida. Aún así, no estoy de acuerdo con su argumento: la única forma de medir el rendimiento real es usar un cronómetro, no mirar los factores constantes en la notación O. Incluso hay casos en que un algoritmo con una función O() más grande vence al otro en situaciones prácticas. –

Cuestiones relacionadas