Poprzednie 65 bajtowe rozwiązanie:
r->{for(int a,b=0,z,i=0;;b=a)if((a=b|1<<(z=r[i++]))==b)return z;}
Nowe rozwiązanie Uwzględniono 19 bajtówimport java.math.*;
-8 bajtów dzięki @Nevay
r->{int z,i=0;for(BigInteger c=BigInteger.ZERO;c.min(c=c.setBit(z=r[i++]))!=c;);return z;}
Wypróbuj online!
Edytować
Algorytm w moim oryginalnym programie był w porządku, ale statyczny rozmiar użytego typu danych oznaczał, że złamał się dość szybko, gdy rozmiar przekroczył określony próg.
Zmieniłem typ danych użyty w obliczeniach, aby zwiększyć limit pamięci programu, aby to uwzględnić (używając BigInteger
dla dowolnej precyzji zamiast int
lub long
). To jednak sprawia, że dyskusyjne jest, czy liczy się to jako O(1)
złożoność przestrzeni.
Wyjaśnienia pozostawiam poniżej nietknięte, ale chciałbym dodać, że obecnie uważam, że niemożliwe jest osiągnięcie O(1)
złożoności przestrzeni bez przyjęcia pewnych założeń.
Dowód
Zdefiniuj N
jako liczbę całkowitą taką, że 2 <= N
.
Niech S
będzie listą reprezentującą serię losowych liczb całkowitych [x{1}, ..., x{N}]
, gdzie x{i}
ma ograniczenie 1 <= x{i} <= N
.
Złożoność czasu (w notacji Big-O) wymagana do iteracji tej listy dokładnie raz na element O(n)
Podane wyzwanie polega na znalezieniu pierwszej zduplikowanej wartości na liście. Mówiąc dokładniej, szukamy pierwszej wartości, S
która jest duplikatem poprzedniego elementu na liście.
Niech p
i q
być pozycje dwóch elementów listy takie, że p < q
i x{p} == x{q}
. Naszym wyzwaniem staje się znalezienie najmniejszego, q
który spełnia te warunki.
Oczywistym podejściem do tego problemu jest iteracja przez S i sprawdzenie, czy nasz x{i}
istnieje na innej liście T
: jeśli x{i}
nie istnieje T
, przechowujemy go T
. Jeśli x{i}
istnieje T
, to jest to pierwsza zduplikowana wartość, a zatem najmniejsza q
, i jako taka zwracamy ją. Ta efektywność przestrzeni wynosi O(n)
.
Aby osiągnąć O(1)
złożoność przestrzeni przy jednoczesnym zachowaniu O(n)
złożoności czasu, musimy przechowywać unikalne informacje o każdym obiekcie na liście w skończonej ilości miejsca. Z tego powodu jedynym sposobem na działanie dowolnego algorytmuO(1)
złożoność przestrzeni występuje, gdy: 1. N otrzymuje górną granicę odpowiadającą pamięci wymaganej do przechowywania maksymalnej liczby możliwych wartości dla określonego skończonego typu danych. 2. Ponowne przypisanie jednej niezmiennej zmiennej nie jest liczone do złożoności, a jedynie liczba zmiennych (lista zawiera wiele zmiennych). 3. (Na podstawie innych odpowiedzi) Lista jest (lub przynajmniej elementy listy są) zmienne, a typ danych listy jest wstępnie ustawiony jako liczba całkowita ze znakiem, co umożliwia wprowadzanie zmian w elementach znajdujących się dalej na liście bez użycia dodatkowej pamięci.
1 i 3 wymagają zarówno założeń, jak i specyfikacji dotyczących typu danych, a 2 wymaga, aby do obliczenia złożoności przestrzeni brana była pod uwagę tylko liczba zmiennych, a nie wielkość tych zmiennych. Jeśli żadne z tych założeń nie zostanie zaakceptowane, osiągnięcie O(n)
złożoności czasowej i O(1)
złożoności przestrzeni byłoby niemożliwe .
Wyjaśnienie
Whoo boy, zajęło to kłopotliwie dużo czasu, by wymyślić odrobinę mocy mózgu.
Tak więc zdobycie bonusu jest trudne. Obaj musimy dokładnie operować na całej liście i śledzić wartości, które już iterowaliśmy, bez dodatkowej złożoności przestrzeni.
Manipulowanie bitami rozwiązuje te problemy. Inicjujemy nasze O(1)
„przechowywanie”, parę liczb całkowitych, a następnie iterujemy listę, LUB-i-ity bit w naszej pierwszej liczbie całkowitej i zapisujemy ten wynik na drugim.
Na przykład, jeśli mamy 1101
i wykonujemy operację LUB 10
, otrzymujemy 1111
. Jeśli zrobimy kolejną operację OR 10
, nadal mamy 1101
.
Ergo, kiedy wykonamy operację OR i skończymy z tym samym numerem, znaleźliśmy nasz duplikat. Brak duplikatów w tablicy powoduje, że program uruchamia się i zgłasza wyjątek.