Właśnie zbombardowałem wywiad i zrobiłem prawie zerowy postęp w kwestii mojego pytania. Czy ktoś może mi powiedzieć, jak to zrobić? Próbowałem wyszukać w Internecie, ale nic nie znalazłem:
Biorąc pod uwagę liczbę, znajdź następny wyższy numer, który ma dokładnie taki sam zestaw cyfr jak numer oryginalny. Na przykład: dane 38276 zwracają 38627
Chciałem zacząć od znalezienia indeksu pierwszej cyfry (od prawej), który był mniejszy niż cyfra jedynek. Następnie obracałbym ostatnie cyfry podzbioru, tak aby była to kolejna największa liczba złożona z tych samych cyfr, ale utknęła.
Ankieter zasugerował również próbę zamiany cyfr pojedynczo, ale nie mogłem rozgryźć algorytmu i po prostu wpatrywałem się w ekran przez około 20-30 minut. Nie trzeba dodawać, że myślę, że będę musiał kontynuować poszukiwanie pracy.
edytuj: za jaką wartość, zostałem zaproszony do następnej rundy wywiadów
next_permutation
;-)Odpowiedzi:
Możesz to zrobić w
O(n)
(gdzien
jest liczba cyfr) w następujący sposób:Zaczynając od prawej, znajdziesz pierwszą parę cyfr, dzięki czemu lewa cyfra jest mniejsza niż prawa cyfra. Odwołajmy się do lewej cyfry przez „digit-x”. Znajdź najmniejszą liczbę większą niż cyfra-x na prawo od cyfry-x i umieść ją bezpośrednio na lewo od cyfry-x. Na koniec posortuj pozostałe cyfry w porządku rosnącym - ponieważ były one już w kolejności malejącej , wystarczy je odwrócić (z wyjątkiem cyfry-x, którą można umieścić we właściwym miejscu
O(n)
) .Przykład wyjaśni to:
Dowód poprawności:
Użyjmy wielkich liter, aby zdefiniować ciągi znaków i małe litery dla cyfr. Składnia
AB
oznacza „łączenie łańcuchówA
iB
” .<
to uporządkowanie leksykograficzne, które jest takie samo jak uporządkowanie liczb całkowitych, gdy ciągi cyfr są równej długości.Nasz oryginalny numer N ma postać
AxB
, gdziex
jest pojedynczą cyfrą iB
jest posortowany malejąco.Liczba znaleziona przez nasz algorytm to
AyC
, gdziey ∈ B
jest najmniejsza cyfra> x
(musi istnieć z powodu wybranego sposobux
, patrz wyżej) iC
jest posortowana rosnąco.Załóżmy, że istnieje pewna liczba (przy użyciu tych samych cyfr),
N'
taka jakAxB < N' < AyC
.N'
musi zaczynać się od tego,A
inaczej nie może się między nimi znaleźć, więc możemy napisać to w formieAzD
. Teraz nasza nierówność jestAxB < AzD < AyC
równa, gdyxB < zD < yC
wszystkie trzy ciągi cyfr zawierają te same cyfry.Aby było to prawdą, musimy to zrobić
x <= z <= y
. Ponieważy
jest najmniejsza cyfra> x
,z
nie może być między nimi, więc alboz = x
alboz = y
. Powiedzmyz = x
. Wtedy nasza nierówność jestxB < xD < yC
, co oznacza,B < D
gdzie zarównoB
iD
mają takie same cyfry. Jednakże, B jest posortowana malejąco, więc nie jest żaden ciąg cyfr z tych większych od niego. Dlatego nie możemy miećB < D
. Po tych samych krokach widzimy, że jeśliz = y
nie możemyD < C
.Dlatego
N'
nie może istnieć, co oznacza, że nasz algorytm poprawnie znajduje następną największą liczbę.źródło
9 832
następnie posortuj wszystko na prawo od 9:9238
Prawie identyczny problem pojawił się jako problem z zacięciem kodu i ma rozwiązanie tutaj:
http://code.google.com/codejam/contest/dashboard?c=186264#s=a&a=1
Oto podsumowanie metody na przykładzie:
A. Podziel sekwencję cyfr na dwie części, aby prawa część była jak najdłuższa, pozostając w malejącej kolejności:
(Jeśli cały numer jest w malejącej kolejności, nie ma większej liczby do zrobienia bez dodania cyfr).
B.1 Wybierz ostatnią cyfrę pierwszej sekwencji:
B.2 Znajdź najmniejszą cyfrę w drugiej sekwencji, która jest większa:
B.3 Zamień je:
C. Posortuj drugą sekwencję w kolejności rosnącej:
D. Gotowe!
źródło
Oto kompaktowe (ale częściowo brutalne) rozwiązanie w Pythonie
W C ++ możesz dokonać takich permutacji: https://stackoverflow.com/a/9243091/1149664 (To ten sam algorytm jak w itertools)
Oto implementacja najważniejszej odpowiedzi opisanej przez Weeble i BlueRaja (inne odpowiedzi). Wątpię, żeby było coś lepszego.
źródło
type 'map' has no len()
. Chciałbym tylko zmienić 2. linię naiis=list(map(int,str(ii)))
. Czy ktoś mógłby wyjaśnić tęif i == 0: return ii
linię? Dlaczego miałby działać z danymi wejściowymi takimi jak 111 lub 531? Dzięki.i == len(iis)
.Oto kilka przykładowych rozwiązań opartych na łańcuchach siłowych, które powinieneś być w stanie wymyślić od razu:
lista
38276
posortowanych cyfr to23678
lista
38627
posortowanych cyfr to23678
przyrost siły brutalnej, sortowanie i porównywanie
Wzdłuż brutalnej siły rozwiązania byłyby konwertowane na ciąg i brutalną siłę wszystkich możliwych liczb za pomocą tych cyfr.
Utwórz ints z nich wszystkich, umieść je na liście i posortuj, uzyskaj następny wpis po wpisie docelowym.
Jeśli spędziłeś na tym 30 minut i przynajmniej nie wymyśliłeś przynajmniej brutalnej siły, ja też cię nie zatrudniłbym.
W świecie biznesu rozwiązanie, które jest nieeleganckie, powolne i niezgrabne, ale umożliwia wykonanie zadania, jest zawsze bardziej wartościowe niż żadne rozwiązanie, fakt, że w zasadzie opisuje całe oprogramowanie biznesowe, nieeleganckie, powolne i niezgrabne.
źródło
źródło
Twój pomysł
jest całkiem niezła. Musisz wziąć pod uwagę nie tylko ostatnią cyfrę, ale wszystkie cyfry o mniejszym znaczeniu niż obecnie rozważane. Ponieważ zanim to zostanie osiągnięte, mamy monotoniczną sekwencję cyfr, która jest skrajną prawą cyfrą mniejszą niż jej prawy sąsiad. Wzgląd
Kolejny większy numer mający te same cyfry to
Znaleziona cyfra jest wymieniana na ostatnią cyfrę - najmniejszą z rozpatrywanych cyfr - a pozostałe cyfry są ułożone w kolejności rosnącej.
źródło
Jestem całkiem pewien, że twój ankieter próbował delikatnie popchnąć cię do czegoś takiego:
Niekoniecznie najbardziej wydajne lub eleganckie rozwiązanie, ale rozwiązuje podany przykład w dwóch cyklach i zamienia cyfry po jednym, tak jak sugerował.
źródło
Weź liczbę i podziel ją na cyfry. Więc jeśli mamy 5-cyfrowy numer, mamy 5 cyfr: abcde
Teraz zamień d i e i porównaj z oryginalnym numerem, jeśli jest większy, masz swoją odpowiedź.
Jeśli nie jest większy, zamień e i c. Teraz porównaj, a jeśli jest mniejszy, zamień d i e ponownie (zauważ rekurencję), weź najmniejszy.
Kontynuuj, aż znajdziesz większą liczbę. Z rekurencją powinno działać jako około 9 linii schematu lub 20 c #.
źródło
To bardzo interesujące pytanie.
Oto moja wersja Java. Poświęć mi około 3 godzin od wymyślenia wzoru, aby całkowicie ukończyć kod, zanim sprawdzę komentarze innych autorów. Cieszę się, że mój pomysł jest taki sam z innymi.
Roztwór O (n). Szczerze mówiąc, nie uda mi się przeprowadzić tego wywiadu, jeśli będzie to tylko 15 minut i będę wymagał pełnego zakończenia kodu na białej tablicy.
Oto kilka interesujących punktów dla mojego rozwiązania:
W każdym kodzie umieszczam szczegółowy komentarz i Big O na każdym kroku.
Oto wynik działający w Intellj:
źródło
Implementacja javascript algorytmu @ BlueRaja.
źródło
Rozwiązanie (w Javie) może wyglądać następująco (jestem pewien, że przyjaciele tutaj mogą znaleźć coś lepszego):
Zacznij zamieniać cyfry od końca łańcucha, aż uzyskasz wyższą liczbę.
Tzn. Najpierw zacznij przesuwać się w górę o niższą cyfrę, a następnie następny wyższy itp., Aż dojdziesz do następnej wyższej.
Następnie posortuj resztę. W twoim przykładzie otrzymasz:
źródło
63872
Dlaczego, co powinno być?Jeśli programujesz w C ++, możesz użyć
next_permutation
:źródło
100
? :-)Odpowiadając na to pytanie, nie wiedziałem nic o algorytmie brutalnej siły, więc podszedłem do niego z innej perspektywy. Postanowiłem poszukać całej gamy możliwych rozwiązań, na które można zmienić tę liczbę, zaczynając od podanej liczby + 1 aż do maksymalnej dostępnej liczby (999 dla liczby 3-cyfrowej, 9999 dla 4 cyfr itp.). Zrobiłem coś w rodzaju znalezienia palindromu ze słowami, sortując liczby każdego rozwiązania i porównując je z posortowaną liczbą podaną jako parametr. Następnie po prostu zwróciłem pierwsze rozwiązanie z szeregu rozwiązań, ponieważ byłaby to kolejna możliwa wartość.
Oto mój kod w Ruby:
źródło
Kod PHP
źródło
Testowałem to tylko z dwiema liczbami. Oni pracowali. Jako kierownik działu IT przez 8 lat, aż do przejścia na emeryturę w grudniu ubiegłego roku, zależało mi na trzech rzeczach: 1) Dokładność: dobrze, jeśli działa - zawsze. 2) Prędkość: musi być do zaakceptowania przez użytkownika. 3) Jasność: Prawdopodobnie nie jestem tak mądry jak ty, ale płacę ci. Wyjaśnij po angielsku, co robisz.
Omar, powodzenia.
źródło
Aby dowiedzieć się, jak to zrobić, zobacz „ Algorytm L ” w „ Sztuce programowania komputerowego Knutha : generowanie wszystkich permutacji ” (.ps.gz).
źródło
Oto mój kod, to zmodyfikowana wersja tego przykładu
Biblioteka:
Test:
źródło
Dodaj 9 do podanej liczby n cyfr. Następnie sprawdź, czy mieści się w limicie (pierwsza (n + 1) cyfra). Jeśli tak, sprawdź, czy cyfry w nowym numerze są takie same jak cyfry w oryginalnym numerze. Powtarzaj dodawanie 9, dopóki oba warunki nie będą spełnione. Zatrzymaj algo, gdy liczba przekroczy limit.
Nie mogłem wymyślić sprzecznego przypadku testowego dla tej metody.
źródło
Kolejne rozwiązanie wykorzystujące Python:
Wynik:
źródło
źródło
Poniżej znajduje się kod do generowania wszystkich permutacji liczby .. chociaż najpierw trzeba przekonwertować tę liczbę całkowitą na ciąg, używając String.valueOf (liczba całkowita).
źródło
źródło
Kolejna implementacja Java, którą można uruchomić po wyjęciu z pudełka i zakończyć testami. Rozwiązaniem jest O (n) przestrzeń i czas przy użyciu starego dobrego programowania dynamicznego.
Jeśli ktoś chce użyć siły, istnieją 2 rodzaje siły:
Zezwól na wszystkie rzeczy, a następnie wybierz min wyżej: O (n!)
Podobnie do tej implementacji, ale zamiast DP, brutalne wykonanie kroku wypełniania mapy indexToIndexOfNextSmallerLeft będzie działało w O (n ^ 2).
źródło
Musimy znaleźć najbardziej prawy bit 0, a następnie 1 i odwrócić ten najbardziej z prawej 0 bit na 1.
na przykład powiedzmy, że nasze dane wejściowe to 487, czyli dwójka 111100111.
odwracamy w prawo najbardziej 0, która ma 1 po nim
więc otrzymujemy 111101111
ale teraz mamy dodatkowe 1 i jeden mniej 0, więc zmniejszamy liczbę 1 po prawej stronie bitu flip o 1 i zwiększamy liczbę 0 bitów o 1, uzyskując
111101011 - dwójkowy 491
źródło
źródło
Oto implementacja Java
Oto testy jednostkowe
źródło
Wiem, że to bardzo stare pytanie, ale wciąż nie znalazłem łatwego kodu w c #. Może to pomóc facetom, którzy biorą udział w wywiadach.
źródło
Bardzo prosta implementacja przy użyciu Javascript, następny najwyższy numer z tymi samymi cyframi
Ponieważ jest wiele komentarzy, więc lepiej skopiować go do edytora tekstu. Dzięki!
źródło
Istnieje wiele dobrych odpowiedzi, ale nie znalazłem przyzwoitej implementacji Java. Oto moje dwa centy:
źródło
źródło