Iterador para una lista de listas ordenadas utilizando una cola de prioridad

Maksim Dmitriev:

He encontrado la siguiente pregunta de la entrevista aquí.

SortedIterator - Consiste en la lista de listas con valores int ordenados en cada lista. Usted tiene que dar el próximo valor de ordenada cuando la llamada siguiente ().

que poner en práctica los métodos constructor * * next () * hasNext ()

[[1, 4, 5, 8, 9], [3, 4, 4, 6], [0, 2, 8]]

next () -> 0, 1, 2, 3, 4, 4, 4 ...

Escribí una rápida implementación en Java:

package com.app;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class SortedIterator implements Iterator<Integer> {

    private final List<Integer> mFlattenedList;
    private final Iterator<Integer> mIntegerIterator;

    SortedIterator(final List<List<Integer>> lists) {
        mFlattenedList = flattenLists(lists);
        mIntegerIterator = mFlattenedList.iterator();
    }

    private List<Integer> flattenLists(final List<List<Integer>> lists) {
        final List<Integer> result = new ArrayList<>();
        for (List<Integer> list : lists) {
            for (int value : list) {
                result.add(value);
            }
        }
        Collections.sort(result);
        return result;
    }

    @Override
    public boolean hasNext() {
        return mIntegerIterator.hasNext();
    }

    @Override
    public Integer next() {
        return mIntegerIterator.next();
    }
}

Tiempo: O (K * N) para aplanar la lista de entrada de listas + O (N * K) para iterar sobre la lista aplanada = O (N * K)

Espacio: O (N * K) para almacenar la lista aplanada.

N - número de listas.

K - número de elementos en cada lista.

Pero la respuesta desde el enlace dice:

Hay una solución con el tiempo la complejidad O (logN) usando una cola de prioridad. Tal vez un entrevistador esperaba algo así, no sé.

¿Cómo es O (log N)posible? Si se utiliza una cola de prioridad, cada vez que llamamos hasNext(), tendremos que comprobar si la cola está vacía ( O(1)). Entonces llamamos next()que extrae el elemento min de la cola ( O(log (N*K)) para cualquier aplicación) de acuerdo con la tabla . Puesto que tenemos que llamar a next()veces N * K, nos lleva O(N * K * log (N*K)a iterar sobre todos los elementos.

pkpnd:

O (logN) La complejidad de la solución es la complejidad por elemento , no la complejidad para iterar sobre todos los valores.

La solución es como la siguiente:

  • En primer lugar definir una nueva clase llamada ListValueque almacena un valor, así como el índice de la lista de vino. Estos deben ser comparable a otros ListValueobjetos utilizando el valor.

  • Constructor: inicializar una PriorityQueue<ListValue>llamada pqy colocar el primer elemento de cada una de las listas de N en pq.

  • next (): Pop the ListValueen la parte delantera pq. El valor en el interior es el valor a devolver, pero en primer lugar, se mueve al siguiente elemento de esa ListValuelista de 's en pq. La complejidad es O (log N), ya que eliminamos un elemento y añadimos un elemento a pq, que contiene en la mayoría de N elementos.

Tenga en cuenta que la solución no conserva todos los valores de N * K en la cola de prioridad a la vez, sólo el único valor "al lado" de cada una de las listas N. Por lo tanto, la cola de prioridad tiene (como máximo) N elementos en todo momento, por lo que sus operaciones son todos O (log N).

Para entender por qué esto funciona, recordemos que cada lista ya está ordenado, por lo que el valor mínimo no utilizada debe aparecer en el "frente" de alguna lista (sin incluir los valores ya consumidos). Luego, nota que la cola de prioridad contiene precisamente el elemento "front" de cada lista - obligamos a que esto suceda en next()cuando añadimos un elemento a pqpartir de la misma lista que el elemento hemos eliminado. Por lo tanto, en todo momento pqcontendrá el valor mínimo no utilizada (hasta que todos los valores son agotado).

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=182178&siteId=1
Recomendado
Clasificación