Znalezienie k-tego najmniejszego elementu z danej sekwencji tylko z czasem O (k) pamięci O (k)


11

Załóżmy, że odczytujemy ciąg n liczb, jeden po drugim. Jak znaleźć k najmniejszy element za pomocą pamięci komórkowej O(k) oraz w czasie liniowym ( O(n) ). Myślę, że powinniśmy zapisać pierwsze k wyrażeń w sekwencji, a kiedy otrzymamy k+1 -ty termin, usuń go, który z pewnością nie może być k -tym najmniejszym elementem, a następnie zapisz k+1 -ty termin. Powinniśmy więc mieć wskaźnik, który pokazuje ten bezużyteczny termin na każdym etapie, a wskaźnik ten powinien być aktualizowany na każdym kroku szybko. Zacząłem od „max”; ale nie można szybko zaktualizować; Oznacza to, że jeśli weźmiemy pod uwagę max, to przy pierwszym usuwaniu pomijamy maksimum i powinniśmy szukać maksimum w O(k) i jego przyczynie (nk)×O(k) czas, że nie jest on liniowy. Może powinniśmy bardziej inteligentnie zapisać pierwsze k warunków sekwencji.

Jak rozwiązać ten problem?


1
Czy jesteś zainteresowany algorytmem online, czy zrobiłby to jakiś algorytm?
Yuval Filmus

Jeśli k=θ(n) , możesz to zrobić za pomocą algorytmu statystyki zamówień. Jeśli k=o(n) , możesz to zrobić Pamięć O(k) i czas O(nlogk) przy użyciu dowolnego drzewa o zrównoważonej wysokości.
Shreesh

To się nazywa problem selekcji en.wikipedia.org/wiki/Selection_algorithm
xavierm02

Istnieją algorytmy czasu lokalnego liniowe, które można wyszukiwać w Google, ale są one nieco skomplikowane.
Yuval Filmus

@ xavierm02 to nie problem identyczny. Ponieważ istnieje ograniczenie limitu pamięci.
Shahab_HK

Odpowiedzi:


16

Utwórz bufor o rozmiarze . Wczytaj 2 k elementów z tablicy. Użyj algorytmu wyboru czasu liniowego, aby podzielić bufor, tak aby k najmniejszych elementów było pierwsze; zajmuje to czas O ( k ) . Teraz wczytaj kolejne k elementów z tablicy do bufora, zastępując k największych elementów w buforze, podziel bufor jak poprzednio i powtórz.2k2kkO(k)kk

To zajmuje czas i O ( k ) przestrzeń.O(kn/k)=O(n)O(k)


+1, to pasuje do zadanych asymptotyków. To powiedziawszy, nie sądzę, że jest to szybsze niż wykonanie pojedynczego algorytmu selekcji w czasie liniowym ... z wyjątkiem sytuacji, gdy jest małą stałą, zapewnia to interesującą perspektywę. Na przykład dla k = 1 ten algorytm tworzy funkcję. kk=1min
orlp

1
Czasami algorytm wyboru czasu liniowego zajmuje zbyt dużo miejsca. Na przykład nie nadaje się do użycia w kontekście przesyłania strumieniowego lub gdy tablica wejściowa jest niezmienna.
jbapple

To są ważne punkty.
orlp

3

O(k)O(nlogk)kO(k)O(logk)O(k+nlogk)O(nlogk)

O(logn)O(n)kk

O(logn)O(k)O(logn)264log264=64kn


O(n×logmin(k,nk))

@ xavierm02 = . Dowód: najgorszym przypadkiem dla jest . Najgorszy przypadek dla to . Są takie same w ramach stałego współczynnika, a zatem = . O(min(k,nk))O(k)knmin(k,nk)n2O(min(k,nk))O(k)
orlp

@ xavierm02 To powiedziawszy, to wciąż niezłe przyspieszenie :)
orlp

un,k=k to ale to nie . Załóżmy, że tak. Potem jest trochę i trochę tak że dla każdego mamy , co jest wyraźnie fałszywe (ponieważ możemy przyjąć Więc . O(k)O(min(k,nk))CMMknkC(nk)n=k+).O(min(k,nk))O(k)
xavierm02

@ xavierm02 Nie znam twojej notacji . Aby być uczciwym, ogólnie nie jestem zaznajomiony z wielowymiarową notacją big- , szczególnie biorąc pod uwagę, że wymiary nie są ze sobą niezwiązane. un,kOn,k
orlp
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.