Oto ulepszenie odpowiedzi aix . Rozważ użycie trzech „warstw” dla struktury danych: pierwsza jest stałą dla pierwszych pięciu cyfr (17 bitów); więc od tej chwili każdy numer telefonu ma tylko pięć pozostałych cyfr. Te pozostałe pięć cyfr traktujemy jako 17-bitowe binarne liczby całkowite i przechowujemy k z tych bitów jedną metodą, a 17 - k = m inną metodą, określając k na końcu, aby zminimalizować wymaganą przestrzeń.
Najpierw sortujemy numery telefonów (wszystkie zredukowane do 5 cyfr dziesiętnych). Następnie liczymy, ile jest numerów telefonów, dla których liczba binarna składająca się z pierwszych m bitów wynosi 0, dla ilu numerów telefonów pierwsze m bitów to maksymalnie 0 ... 01, dla ilu numerów telefonów pierwsze m bity mają wartość co najwyżej 0 ... 10 itd., aż do liczby numerów telefonów, dla których pierwsze m bitów to 1 ... 11 - ta ostatnia liczba to 1000 (dziesiętnie). Jest 2 ^ m takich zliczeń, a każda z nich to najwyżej 1000. Jeśli pominiemy ostatnią (bo i tak wiemy, że jest to 1000), możemy przechowywać wszystkie te liczby w ciągłym bloku (2 ^ m - 1) * 10 bitów. (10 bitów wystarczy do zapisania liczby mniejszej niż 1024).
Ostatnie k bitów wszystkich (zredukowanych) numerów telefonów jest przechowywanych w sposób ciągły w pamięci; więc jeśli k jest, powiedzmy, 7, to pierwsze 7 bitów tego bloku pamięci (bity od 0 do 6) odpowiada ostatnim 7 bitom pierwszego (zmniejszonego) numeru telefonu, bity od 7 do 13 odpowiadają ostatnim 7 bitom drugiego (zmniejszonego) numeru telefonu itp. Wymaga to 1000 * k bitów, co daje łącznie 17 + (2 ^ (17 - k ) - 1) * 10 + 1000 * k , co daje minimum 11287 dla k daje = 10. Więc możemy przechowywać wszystkie numery telefonów w ceil ( 11287/8) = 1411 bajtów.
Dodatkową przestrzeń można zaoszczędzić, zauważając, że żadna z naszych liczb nie może zaczynać się np. Od np. 1111111 (binarnie), ponieważ najniższa liczba zaczynająca się od tego to 130048, a mamy tylko pięć cyfr dziesiętnych. To pozwala nam zaoszczędzić kilka wpisów z pierwszego bloku pamięci: zamiast 2 ^ m - 1 zliczeń potrzebujemy tylko ceil (99999/2 ^ k ). Oznacza to, że formuła staje się
17 + ceil (99999/2 ^ k ) * 10 + 1000 * k
co zadziwiająco osiąga swoje minimum 10997 zarówno dla k = 9, jak i k = 10, czyli ceil (10997/8) = 1375 bajtów.
Jeśli chcemy wiedzieć, czy dany numer telefonu jest w naszym zestawie, najpierw sprawdzamy, czy pierwsze pięć cyfr binarnych odpowiada pięciu cyfrom, które zapisaliśmy. Następnie podzielimy pozostałe pięć cyfr na jego górne m = 7 bitów (czyli, powiedzmy, m- bitową liczbę M ) i jej dolne k = 10 bitów (liczba K ). Znajdujemy teraz liczbę a [M-1] zredukowanych numerów telefonów, dla których pierwsze m cyfr to co najwyżej M - 1, oraz liczbę a [M] zredukowanych numerów telefonów, dla których pierwsze [M-1] i bity w drugim bloku pamięci, aby sprawdzić, czy znajdziemy m cyfr to co najwyżej M , oba z pierwszego bloku bitów. Teraz sprawdzamy między a [M] tą sekwencję z k K ; w najgorszym przypadku takich sekwencji jest 1000, więc jeśli korzystamy z wyszukiwania binarnego, możemy zakończyć operacjami O (log 1000).
Pseudokod do wydrukowania wszystkich 1000 liczb następuje, gdzie mam dostęp do K ' k -bitowe wejście pierwszego bloku pamięci, jak w [K] i M ” th m wejścia bitowych drugiego bloku pamięci jako b [m]; (obie te operacje wymagałyby kilku bitowych operacji, których zapisywanie jest żmudne). Pierwsze pięć cyfr to liczba c .
i := 0;
for K from 0 to ceil(99999 / 2^k) do
while i < a[K] do
print(c * 10^5 + K * 2^k + b[i]);
i := i + 1;
end do;
end do;
Może coś pójdzie nie tak z przypadkiem granicznym dla K = ceil (99999/2 ^ k ), ale to dość łatwe do naprawienia.
Wreszcie, z punktu widzenia entropii, nie jest możliwe przechowywanie podzbioru 10 ^ 3 dodatnich liczb całkowitych, z których wszystkie są mniejsze niż 10 ^ 5 w liczbie mniejszej niż ceil (log [2] (dwumian (10 ^ 5, 10 ^ 3)) ) = 8073. Uwzględniając 17, których potrzebujemy na pierwsze 5 cyfr, nadal istnieje luka 10997 - 8090 = 2907 bitów. Ciekawym wyzwaniem jest sprawdzenie, czy istnieją lepsze rozwiązania, w których nadal można stosunkowo skutecznie uzyskać dostęp do numerów!