Algoritmos: ¿Cómo sumo O (n) y O (nlog (n)) juntos?

22

Tengo el siguiente algoritmo que encuentra duplicados y los elimina:

public static int numDuplicatesB(int[] arr) {
    Sort.mergesort(arr);
    int numDups = 0;
    for (int i = 1; i < arr.length; i++) {
        if (arr[i] == arr[i - 1]) {
            numDups++;
} }
    return numDups;
}

Estoy tratando de encontrar la peor complejidad de tiempo en este caso. Sé que mergesort es nlog(n), y en mi bucle for estoy iterando sobre todo el conjunto de datos para que eso cuente como n. Sin embargo, no estoy seguro de qué hacer con estos números. ¿Debería resumirlos juntos? Si tuviera que hacer eso, ¿cómo lo haría?

chopper draw lion4
fuente
1
Nota al margen: puede usar una tabla hash para hacer esto en O (n) dependiendo de los requisitos de memoria.
corsiKa

Respuestas:

67
O(n) + O(n log(n)) = O(n log(n))

Para la complejidad de Big O, lo único que le importa es el término dominante. n log(n)domina nasí que ese es el único término que te importa.

Justin Cave
fuente
44
Otra forma de pensar en esto es imaginar que su procesamiento de O (n) fue realmente O (n log n), como si hiciera dos tipos independientes. Entonces tendría 2 * O (n log n). Pero las constantes disminuyen, así que regresas a O (n log n).
Jonathan Eunice
44
@ Jonathan Si bien eso funciona en la práctica, es muy cierto que O (n) no es igual a O (n log (n)), por lo que no recomendaría usarlo de forma regular.
Aza
17
@Emrakul en realidad creo que el razonamiento es teóricamente sólido y práctico. O (n) es un subconjunto apropiado de O (n log (n)). Entonces, si f (n) pertenece a O (n), también pertenece a O (n log (n)).
emory
17
Cabe señalar que cuando decimos f(n) is O(g(n))lo que realmente estamos diciendo es que la función f is a member of the set of functions that grows at the rate of at most g(n) over the long term. Esto significa que todos los miembros de O(n)son también miembros de O(n*log(n)). Las +expresiones en como se O(f(n)) + O(g(n))refieren realmente a la unión de conjuntos (cuál de ustedes es realmente pedante, realmente debería usar ∪).
Lie Ryan
3
@LieRyan Originalmente, no se establece la unión, pero suma fija: A + B = { a + b | a in A, b in B }. Sucede que para conjuntos de la forma O(g(n))esto es lo mismo que la unión de conjuntos, ya que uno de los conjuntos es siempre un subconjunto del otro, y ambos son invariables a las sumas (es decir, A + A = A). (Vaya, Nate escribió esencialmente lo mismo).
Paŭlo Ebermann
56

Razonemos nuestro camino y recordemos la definición de O. El que voy a usar es para el límite en el infinito.

Tiene razón al afirmar que realiza dos operaciones con los límites asintóticos correspondientes de O(n)y, O(nlog(n))pero combinarlos en un solo límite no es tan simple como agregar las dos funciones. Usted sabe que su función lleva al menos O(n)tiempo y también al menos O(nlog(n))tiempo. Entonces, realmente la clase de complejidad para su función es la unión de O(n)y, O(nlog(n))pero O(nlog(n))es un superconjunto de, O(n)así que realmente es justa O(nlog(n)).

davidk01
fuente
12
+1 esta debería ser la respuesta. Describe la respuesta con mayor precisión utilizando términos de compsci.
5

Si fuera a exponerlo a mano, se vería más o menos así:

Supongamos que el tiempo total es: an + bn log (n), donde a y b son constantes (ignorando los términos de orden inferior).

Cuando n va al infinito (an + bn log (n)) / n log (n) -> a / log (n) + b -> b

Entonces, el tiempo total es O (bn log (n)) = O (n log (n)).

richardb
fuente
2

Comience con la definición de O ():

O (n log n) significa "menor que C n log n, si n es grande".

O (n) significa "menor que D n, si n es grande".

Si agrega ambos, el resultado es menor que C n log n + D n <C n log n + D n log n <(C + D) n log n = O (n log n).

En general, si f (n)> C g (n) para n grande y algo de C> 0, entonces O (f (n)) + O (g (n)) = O (f (n)). Y después de hacer algunos casos usando la definición de O (), sabrá lo que puede y no puede hacer.

gnasher729
fuente
1

La gran notación O se define como un conjunto:

ingrese la descripción de la imagen aquí

Por lo tanto, ingrese la descripción de la imagen aquícontiene todas las funciones que son, a partir de un punto grande arbitrario ingrese la descripción de la imagen aquí, siempre más pequeñas que g.

Ahora, cuando tiene una función que está dentro ingrese la descripción de la imagen aquíy luego ejecuta otra que aumenta más lentamente que g, ciertamente aumenta más lentamente que 2g. Por lo tanto, ejecutar algo más lento que g no cambiará la clase de complejidad.

Más formalmente:

f, h \ in \ mathcal {O} (g) \ Rightarrow (f + h) \ in \ mathcal {O} (g)

Puedes probarlo fácilmente.

TL; DR

Aún es n log (n)

Martin Thoma
fuente