Jak znaleźć medianę liczb w czasie liniowym za pomocą stosów?

Wikipedia mówi:

Algorytmy wyboru: znajdowanie min, max, zarówno min jak i max, mediana , lub nawet k-ten największy element może być wykonane w czasie liniowym za pomocą stosów.

Wszystko, co mówi, to to, że można to zrobić, a nie jak.

Możesz mi dać jakiś Początek, jak to można zrobić za pomocą sterty?

Author: Lazer, 2010-04-05

7 answers

Można użyć sterty min-max-median, aby znaleźć min, max i median w stałym czasie (i potrzeba czasu liniowego, aby zbudować stertę). Możesz użyć drzewa order-statistics, aby znaleźć najmniejszą/największą wartość kth. Obie te struktury danych są opisane w niniejszej pracy na stosach min-max [link pdf] . Min-max heaps to sterty binarne, które zmieniają się między min-heaps i max-heaps.

Z artykułu: sterta min-max-mediana jest stertą binarną o następujących właściwościach:

1) Mediana wszystkich elementów znajduje się w korzeniu

2) lewy podzbiór pierwiastka jest Min-max sterty Hl wielkości sufitu [((n-1)/2)] zawierające elementy mniejsze lub równe medianie. Właściwy podzbiór to sterta Max-min o wielkości podłogi [((n-1)/2)] zawierająca tylko elementy większe lub równe medianie.

Artykuł wyjaśnia, jak zbudować taką stertę.

Edit: po dokładniejszym przeczytaniu artykułu wydaje się, że budowanie min-max-środkowych stosów wymaga, aby najpierw znaleźć medianę (FTA: "Znajdź medianę wszystkich N elementów przy użyciu jednego ze znanych algorytmów czasu liniowego"). To powiedziawszy, po zbudowaniu sterty możesz utrzymać medianę po prostu utrzymując równowagę między stertą min-max po lewej i stertą max-min po prawej. DeleteMedian zastępuje root albo min stosu max-min albo Max stosu min-max (w zależności od tego, która z tych wartości utrzymuje równowagę).

Więc jeśli planujesz użyć min-max-mediana sterta, aby znaleźć medianę stałego zestawu danych jesteś SOL, ale jeśli używasz go na zmieniającym się zestawie danych jest to możliwe.

 21
Author: Niki Yoshiuchi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-11 22:53:29

Zobacz tę stronę Wikipedii na algorytmy wyboru . W szczególności przyjrzyj się algorytmowi bfprt i algorytmowi Mediana Medianów. Bfprt jest probabilistycznie liniowy, i jest wzorowany na quicksort; Mediana Medians jest gwarantowana liniowa, ale ma duży stały współczynnik i tak może trwać dłużej w praktyce, w zależności od wielkości zestawu danych.

Jeśli masz tylko kilkaset lub tysiące elementów, z których można wybrać medianę, podejrzewam, że prosty quicksort następnie bezpośrednie indeksowanie jest najłatwiejsze.

 4
Author: Dale Hagglund,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-05 18:08:17

Są prawdopodobnie lepsze algorytmy, ale oto jak bym to zrobił:

Mają dwa wiadra i wartość. Wartość jest mediana, dwa wiadra są "większe niż mediana" i "mniejsze niż mediana". Dla każdego elementu x w tablicy, równoważenie kubełków jest takie, że big_bucket i small_bucket różnią się rozmiarem nie większym niż 1. Podczas przenoszenia przedmiotów z dużego wiadra do małego wiadra najpierw muszą przejść przez wartość średnią, aby się tam dostać (tzn. różnica 2 będzie pomyślnie przesuń element z jednego wiadra do następnego-różnica 1 spowoduje przesunięcie elementu z jednego wiadra do wartości Środkowej.) Na końcu pierwszego przejścia przez tablicę wartość powinna być twoją medianą.

 4
Author: fbrereto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-05 18:08:44

Być może nie było tego w pobliżu, kiedy zadano pierwotne pytanie, ale teraz wiki ma link do źródła, a tutaj jest: http://ftp.cs.purdue.edu/research/technical_reports/1991/TR%2091-027.pdf

Konkretnie, Przejdź na stronę 17 i spójrz na opis RSEL4. Dowodzą one w twierdzeniu 3.2, że złożoność czasowa tego k-tego algorytmu doboru wynosi O (k). więc potrzeba O(n), aby zbudować stertę, i dodatkowe o(k), aby znaleźć k-ten najmniejszy element.

Its not really as prosto do przodu, jak sugerowały niektóre inne odpowiedzi

 3
Author: Shlomi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-15 00:36:56

Jeśli wiesz więcej o strukturze danych sterty, łatwo zrozumiesz, że tak naprawdę jest. struktura sterty może być zbudowana w czasie O (n) , jest min sterta i Max sterta. element korzeniowy min heap da ci najmniejszy element. element główny sterty max daje element max. Po prostu budując stertę znajdujesz min i max. ten sam pomysł dla mediana i kth największy, podczas budowania sterty, można znaleźć mediana i kth największy patrząc na lewej lub prawej gałęzi drzewa i zachowując stałą ilość pamięci do przechowywania numeru elementu. itd.

 0
Author: DarthVader,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-08 03:32:37

Zapisz pierwszą liczbę całkowitą w tablicy i ustaw licznik na 1. Następnie Pętla przez pozostałe liczby całkowite w wektorze. Jeżeli bieżąca liczba całkowita w tablicy jest taka sama jak zapisana, licznik jest zwiększany o jeden, w przeciwnym razie licznik jest zmniejszany o jeden. Jeśli licznik kiedykolwiek osiągnie zero, wyrzuć zapisaną liczbę całkowitą i zastąp ją bieżącą liczbą całkowitą w tablicy. Kiedy w końcu przejrzysz wszystkie liczby całkowite, zostaje Ci jeden kandydat. Następnie musisz przejść przez tablica ponownie i policzyć wystąpienie kandydata, aby sprawdzić, czy to naprawdę jest dominator.

static int FindDominator(int[] arr)
{
int counter = 1;
int candidate = arr[0];
for(int i = 1; i < n; i++)
{
   if(arr[i] == candidate) counter++
    else 
   {
        counter--;
        if(counter == 0) { candidate = arr[i]; counter = 1; }
    }
}
counter = 0;
for(int i = 0;  i < n; i++)
{
    if(arr[i] == candidate) counter++;
}
if(counter > n / 2) return candidate;
else return -1;
}
 0
Author: jaycee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-26 17:34:17

Oczywiście min i max W O (n) są łatwe i nie wymagają sterty.

K ' - ty największy można zrobić dość prosto, utrzymując stertę wielkości k z najwyższych wartości k do tej pory. Runtime to O (n*logk). Można nazwać ten czas liniowy, jeśli k jest stałą wielkością i k

Myślę, że mediana nie jest jednak możliwa. Samo utworzenie sterty O(n) wymaga czasu O(N*logn).

Edit: Ok, po zastanowieniu się nad tym trochę więcej, IVlad ma rację. Możesz utworzyć stertę w O (n), dla ustalonego rozmiaru. Ale... to nie pomaga operacji z jego medianą. Technika tworzenia sterty liniowej wytwarza tylko poprawną stertę jako jej końcowy wynik. Proste podejście do robienia N wstawek, skutkujące poprawną stertą po każdym kroku to O(n * logn).

Wydaje mi się, że użycie sterty do znalezienia mediany wymagałoby użycia tych uruchomionych pod-sterty. Na przykład, była tu zamieszczona odpowiedź (która wydaje się być teraz usunięta), która łączyła się z postem na blogu sugerującym algorytm dla tego problemu. Śledził biegową medianę za pomocą dwóch stosów (mniejsza połowa i większa połowa), ponieważ wykonuje pojedyncze przejście przez dane. Wymagałoby to wolniejszego, naiwnego podejścia do sterty, ponieważ polega ono na utrzymywaniu poprawnych Stert podczas wstawiania i usuwania z nich.

Czy Jest jakiś inny sposób, aby znaleźć medianę przy użyciu techniki liniowego tworzenia sterty jednego strzału?

 -1
Author: Alan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-05 19:44:20