2009-10-29 11 views
6

To jest problem opisane w Programming pearls. Nie rozumiem metody binarnego wyszukiwania opisanej przez autora. Czy ktoś może pomóc w opracowaniu? Dzięki.Znajdź brakującą 32-bitową liczbę całkowitą wśród nieposortowanych tablic zawierających co najwyżej 4 miliardy int.

EDYCJA: Rozumiem ogólnie wyszukiwanie binarne. Po prostu nie mogę zrozumieć, jak zastosować wyszukiwanie binarne w tym szczególnym przypadku. Jak zdecydować, brakujący numer znajduje się w pewnym zakresie, abyśmy mogli wybrać inny. Angielski nie jest moim ojczystym językiem, to jeden z powodów, dla których nie potrafię dobrze zrozumieć autora. Tak więc, użyj zwykłego angielskiego proszę :)

EDYCJA: Dziękuję wszystkim za wspaniałą odpowiedź i komentarze! Najważniejszą lekcją, jaką mogę odnieść z rozwiązania tego pytania, jest Wyszukiwanie binarne dotyczy nie tylko posortowanej tablicy!

+0

Której części nie rozumiesz? Czy możesz rozwinąć? – dirkgently

+3

Wyszukiwanie binarne jest rozwiązaniem innego problemu. Nie nadaje się do znalezienia wartości w nieposortowanym zakresie. –

+0

Czego nie możesz zrozumieć? Binary search w ogóle lub po prostu opis autorów? –

Odpowiedz

9

jest trochę więcej informacji na this web site Cytowany stamtąd..

„to jest pomocne, by zobaczyć tę binarny szukaj w terminach dwudziestu bitów reprezentujących każdą liczbę całkowitą w pierwszym przebiegu algorytmu odczytujemy (najwyżej) milion wejściowych liczb całkowitych i piszemy te z wiodącym bitem zerowym na jedną taśmę i te z wiodącym bitem do innej taśmy. Jedna z tych dwóch taśm zawiera co najwyżej 500 000 liczb całkowitych, więc następnie używamy tej taśmy jako bieżącego wejścia i powtarzamy proces sondy, ale tym razem na drugim bicie. Jeśli oryginalna taśma wejściowa zawiera N elementów, pierwsze przejście odczytuje liczby całkowite N, drugie przejście najwyżej N/2, trzecie przejście co najwyżej N/4, i tak dalej, więc całkowity czas działania jest proporcjonalny do N. brakująca liczba całkowita może zostać znaleziona przez sortowanie na taśmie, a następnie skanowanie, ale wymagałoby to czasu proporcjonalnego do N log N. "

Jak widać, jest to wariacja algorytmu binarnego wyszukiwania: podziel problem na dwie części i rozwiązać problem dla jednego z mniejszych elementów.

+0

Jeśli dobrze pamiętam, 1 + 1/2 + 1/4 .. = Sum (1/2^n) zmierza w kierunku 2. Dlatego to podejście jako złożoność O (2N) –

+2

To nie jest prawda. Złożoność jest faktycznie O (log n). Załóżmy, że przestrzeń problemu wynosi 8 (więc musimy znaleźć brakującą liczbę całkowitą w zakresie 0,1,2,3,4,5,6,7). Wymaga to co najwyżej 3 przebiegów algorytmu. Jeśli podwoimy obszar problemowy do 16, wymagamy maksymalnie 4 przebiegów algorytmu. Tak więc, mimo że przestrzeń problemu podwoiła się z 8 do 16, czas potrzebny na rozwiązanie problemu zwiększył się tylko o czynnik 1,33333 ... Jeśli podwoimy ponownie, czas potrzebny na rozwiązanie problemu wzrasta tylko o współczynnik 1,25 . Co oznacza, że ​​złożoność algorytmu nie jest liniowa (więc nie O (2n)). –

+7

W momencie, w którym wykonaliśmy jedno pełne przejście przez dane, złożoność to O (n), więc O (log (n)) jest już na wyczerpaniu. Teraz O (n) oznacza, że ​​istnieje pewna stała, c, taka, że ​​czas działania algorytmu jest ograniczony od góry przez c * n, więc O (2n) jest dokładnie taki sam jak O (n). rwwilden, twój błąd polegał tylko na liczeniu pasaży, gdy wartość podwojenia również podwaja się. –

1

Cóż, chodzi o plik zawierający wszystkie 4 miliardy całkowite z wyjątkiem jednego! To jest haczyk w tym przypadku.

  1. Podczas poruszania się po liście liczb całkowitych, oblicz sumę.
  2. Na koniec oblicz sumę tak, jakby były wszystkie liczby całkowite za pomocą wzoru N * (N + 1)/2
  3. Wyodrębnij sumę w (1) z sumy obliczonej w (2). To jest brakująca liczba całkowita.

Przykład: Załóżmy, że mamy następującą sekwencję: 9 3 2 8 4 10 6 1 7 (1 do 10 z 5 brakującymi). Gdy dodamy liczby całkowite sekwencyjnie, otrzymujemy 9 + 3 + 2 + 8 + 4 + 10 + 6 + 1 + 7 = 50. Suma wszystkich liczb całkowitych od 1 do 10 wynosi 10 * (10 + 1)/2 = 55 Dlatego brakująca liczba całkowita to 55 - 50 = 5. QED

+0

Nie, to nieposortowany zakres. Jednakże masz rację, że istnieje więcej niż jedna luka (problem mówi co najwyżej 4 miliardy liczb całkowitych) –

+0

chodzi o plik, który zawiera co najwyżej 4 miliardy liczb całkowitych (może zawierać mniej), co oczywiście nie jest całym zakresem int32 . musisz znaleźć co najmniej jedną z 32-bitowych liczb całkowitych, których nie ma w pliku. –

+0

(przepraszam za usunięcie usuniętej odpowiedzi, błędnie przeczytałem problem także za pierwszym razem) –

2

Wierzę w to, do czego dąży autor, że wybrałeś środek twojego aktualnego zakresu liczb całkowitych i przygotowałeś dwa pliki wyjściowe. Podczas czytania danych wszystko powyżej punktu środkowego przechodzi do jednego pliku, a wszystko poniżej punktu środkowego przechodzi do drugiego.

Po zakończeniu wybierz mniejszy plik, a następnie powtórz operację, używając [dolnego ograniczenia, środka] lub (punktu środkowego, górnej granicy) jako nowego zakresu, aż plik i zakres są wystarczająco małe aby przełączyć się na wzór bitmapy (lub jeden z Twoich plików wyjściowych jest pusty)

Damien

+0

Przez jakie kryterium wybierasz górną połowę i dolną połowę? Ponieważ elementy są nieposortowane. –

+0

@rwwilden - Nie jestem pewien, czy rozumiem twoje zapytanie? Jeśli pytasz, z którą połową pracujesz, wierzę, że odpowiedziałem na to (mniejszy plik, który został wskazany w tekście problemu) –

+0

@rwwilden - Myślę, że mogłem być niejasny - kiedy mówiłem o zasięgu, i środkowy, miałem na myśli wartości numeryczne, a nie ich pozycję w pliku wejściowym. Zasadniczo opublikowaliśmy ten sam opis. –

2

Ogólna koncepcja: wybierz zakres liczb całkowitych i wybierz wszystkie liczby całkowite mieszczące się w tym przedziale. Jeśli liczba liczb całkowitych jest mniejsza niż wielkość twojego zasięgu, wiesz, że ten zakres zawiera jedną lub więcej brakujących liczb.

Dotyczy to również pierwotnego problemu, ponieważ wiesz, że w niektórych miejscach są również brakujące numery.

2

Jeśli rozważasz liczby w zakresie od 1 do N; połowa z nich jest większa niż N/2, a połowa z nich jest mniejsza niż N/2

Te większe niż N/2 miałyby MSB ustawiony na jeden; MSB = 0 dla mniejszych.

Partition cały zestaw oparty na MSB który daje dwa zbiory: zbiór liczb mniejszych niż N/2 oraz zestaw liczby większej niż N/2

Partycja mniejsze ma brakujący element .

W następnym kroku użyj następnego MSB.

  1. Jeżeli mniejszy zestaw był mniejszy niż N/2, połowa z nich jest mniejsza niż N/4 (2 MSB = 0), a drugą połowę większa od N/4 (2 MSB = 1)

  2. Jeśli mniejszy zestaw był większy niż N/2, połowa z nich jest mniejsza niż N/2 + N/4 (2. MSB = 0), a druga połowa większa niż N/2 + N/4 (2. MSB = 1)

Każda runda dzieli o połowę przestrzeń poszukiwań i to wszystko.

Sum (N/2^i) for 0 <= i < log N gives you O(N) 
2

Jest to w zasadzie to samo pytanie, co this question. To samo podejście działa w przypadku dużej ilości pamięci, aby uzyskać złożoność O (N). Zasadniczo po prostu rekurencyjnie spróbuj umieścić każdą liczbę całkowitą w jej poprawnej lokalizacji i zobacz, co nie ma poprawnej wartości.