To jest pytanie do wywiadu z Google. Nie jestem w stanie sam tego rozwiązać. Czy ktoś może rzucić trochę światła?
Napisz program, który wydrukuje sekwencję naciśnięć klawiszy tak, aby generował maksymalną liczbę znaków „A”. Masz prawo do korzystania tylko 4 przyciski: A, Ctrl+ A, Ctrl+ Ci Ctrl+ V. Dozwolonych jest tylko N naciśnięć klawiszy. Wszystkie Ctrlznaki + są traktowane jako jedno naciśnięcie klawisza, więc Ctrl+ Ato jedno naciśnięcie klawisza.
Na przykład sekwencja A, Ctrl+ A, Ctrl+ C, Ctrl+ Vtworzy dwie jest w 4 klawiszy.
- Ctrl + A to Zaznacz wszystko
- Ctrl + C to kopia
- Ctrl + V to Wklej
Zrobiłem trochę matematyki. Dla dowolnego N, używając x liczb A, jeden Ctrl+ A, jeden Ctrl+ Ci y Ctrl+ V, możemy wygenerować max ((N-1) / 2) 2 liczby A. Od pewnego N> M, lepiej jest użyć tylu Ctrl+ A„s, Ctrl+ Ci Ctrl+ Vsekwencje jak to podwaja liczbę jest.
Sekwencja Ctrl+ A, Ctrl+ V, Ctrl+ Cnie nadpisze istniejącego zaznaczenia. Doda skopiowane zaznaczenie do zaznaczonego.
^A
jest zwykle „zaznacz wszystko”,^C
„kopiuj”,^V
„wklej”. Czy to daje ci pomysł?Odpowiedzi:
Istnieje dynamiczne rozwiązanie do programowania. Zaczynamy, wiedząc, że 0 kluczy może dać nam 0 szóstek. Następnie iterujemy
i
aż don
, wykonując dwie rzeczy: naciskając raz A i naciskając zaznacz wszystko + kopiuj, a następniej
czasy wklejania (właściwiej-i-1
poniżej; zwróć uwagę na tę sztuczkę: zawartość nadal znajduje się w schowku, więc możemy wkleić ją wiele razy bez kopiowanie za każdym razem). Musimy wziąć pod uwagę tylko 4 kolejne wklejanie, ponieważ zaznacz, kopiuj, wklej x 5 jest równoważne zaznaczaniu, kopiowaniu, wklejaniu, zaznaczaniu, kopiowaniu, wklejaniu, a to drugie jest lepsze, ponieważ pozostawia nam więcej w schowku. Kiedy już osiągnęliśmyn
, mamy pożądany rezultat.Złożoność może wydawać się O (N), ale ponieważ liczby rosną w tempie wykładniczym, w rzeczywistości jest to O (N 2 ) ze względu na złożoność mnożenia dużych liczb. Poniżej znajduje się implementacja Pythona. Obliczenie dla N = 50 000 zajmuje około 0,5 sekundy.
W kodzie
j
reprezentuje całkowitą liczbę klawiszy naciśniętych po naszej nowej sekwencji naciśnięć klawiszy.i
Na tym etapie mamy już naciśnięcia klawiszy, a 2 nowe naciśnięcia klawiszy służą do wybierania wszystkiego i kopiowania. Dlatego osiągamyj-i-2
czasy wklejania . Ponieważ wklejanie dodaje do istniejącej sekwencjidp[i]
A
, musimy dodać1
ją tworzącj-i-1
. To wyjaśniaj-i-1
w przedostatnim wierszu.Oto kilka wyników (
n
=> liczba liter A):Zgadzam się z @SB, że zawsze powinieneś podawać swoje założenia: Moje jest takie, że nie musisz wklejać dwa razy, aby podwoić liczbę znaków. To daje odpowiedź na 7, więc jeśli moje rozwiązanie jest błędne, założenie musi być poprawne.
W przypadku gdy ktoś zastanawia się, dlaczego nie jestem sprawdzanie sekwencji postaci Ctrl+ A, Ctrl+ C, A, Ctrl+ V: Wynik końcowy będzie zawsze taka sama jak A, Ctrl+ A, Ctrl+ C, Ctrl+ Vktóre należy rozważyć.
źródło
n => result
czyresult => n
? Tak czy inaczej, myślę, że to źle. Możemy wpisać 9 Tak jak z 7 naciśnięciami klawiszy. Jeśli jestn => result
to zdecydowanie złe. Liczba znaków As you can nie może być mniejsza niżn
.n => result
. Mówisz: „Możemy wpisać 9, tak jak w przypadku 7 naciśnięć klawiszy”, co otrzymuję. Przeczytaj „sztuczkę”, którą właśnie zredagowałem w.n
to naciśnięcia klawiszy, których możesz używać. Musisz obliczyć, ile As możesz wpisać za pomocąn
klawiszy. Więc7 => 7
nie ma sensu.O(n)
a nawetO(1)
:).Korzystając z rozwiązania marcog, znalazłem wzór, który zaczyna się od
n=16
. Aby to zilustrować, oto skróty klawiszowen=24
don=29
, zamieniłem ^ A na S (wybierz), ^ C na C (kopiowanie) i ^ V na P (wklej) dla czytelności:Po początkowych 4 As, idealnym wzorcem jest zaznaczanie, kopiowanie, wklejanie, wklejanie, wklejanie i powtarzanie. Spowoduje to pomnożenie liczby As przez 4 co 5 naciśnięć klawiszy. Jeśli ten wzór 5 naciśnięć klawiszy nie może samodzielnie zużywać pozostałych naciśnięć klawiszy, pewna liczba 4 wzorców naciśnięć klawiszy (SCPP) zużywa ostatnie naciśnięcia klawiszy, zastępując SCPPP (lub usuwając jedną z past) w razie potrzeby. 4 wzorce naciśnięć klawiszy mnożą sumę przez 3 co 4 naciśnięcia.
Używając tego wzorca tutaj, jest kod Pythona, który daje takie same wyniki jak rozwiązanie marcog, ale jest to edycja O (1) : To jest w rzeczywistości O (log n) z powodu potęgowania, dzięki IVladowi za wskazanie tego.
Obliczanie e3: Na końcu listy naciśnięć klawiszy zawsze znajduje się od 0 do 4 wzorców SCPP, ponieważ
n % 5 == 4
są 4,n % 5 == 1
są 3,n % 5 == 2
są 2,n % 5 == 3
jest 1 in % 5 == 4
jest 0. Można to uprościć do(4 - n) % 5
.Obliczanie e4: Całkowita liczba wzorów wzrasta o 1 za każdym razem
n % 5 == 0
, gdy okazuje się, że liczba ta rośnie dokładnien / 5
. Korzystając z podziału piętra, możemy uzyskać całkowitą liczbę wzorów, łączna liczbae4
to całkowita liczba wzorów minuse3
. Dla osób niezaznajomionych z Pythonem//
jest to przyszłościowa notacja podziału pięter.źródło
n=3000
, więc prawdopodobnie tak jest. (Szkoda, że nie mam dzisiaj głosów: /)O(1)
ponieważ potęgowania nie można wykonać w stałym czasie. To jestO(log n)
.Oto, jak bym do tego podejść:
biorąc pod uwagę tekst, do jego skopiowania potrzeba 4 naciśnięć klawiszy:
Stamtąd możesz rozważyć zrobienie 4 lub 5 A, a następnie powtórzenie powyższego. Pamiętaj, że działanie
ctrl + a, c, v, v
spowoduje wykładniczy wzrost tekstu w trakcie przeglądania. Jeśli pozostałe pociągnięcia są <4, po prostu rób dalejCtrlVKluczem do wywiadów w miejscach takich jak Google jest przedstawienie swoich założeń i przekazanie swoich przemyśleń. chcą wiedzieć, jak rozwiązujesz problemy.
źródło
ACVV-VVVVV
mnoży się przez 7,ACVV-ACVV-V
mnoży przez 6. Tak więc Ctrl-V dla pozostałych uderzeń <6 zamiast 4.Można to rozwiązać w O (1): Podobnie jak w przypadku liczb Fibonacciego, istnieje wzór do obliczenia liczby wydrukowanych As (i sekwencji naciśnięć klawiszy):
1) Możemy uprościć opis problemu:
równa się
2) Możemy opisać sekwencję naciśnięć klawiszy jako ciąg N znaków z {'*', 'V', 'v'}, gdzie 'v' oznacza [Cv], a '*' oznacza [Ca] i 'V „oznacza [DW]. Przykład: „vvvv * Vvvvv * Vvvv”
Długość tego sznurka nadal jest równa N.
Iloczyn długości słów Vv w tym ciągu jest równy liczbie wyprodukowanych As.
3) Biorąc pod uwagę stałą długość N dla tego ciągu i stałą liczbę K słów, wynikiem będzie maksymalna, jeśli wszystkie słowa mają prawie taką samą długość. Ich różnica w parach nie przekracza ± 1.
Jaka jest optymalna liczba K, jeśli podano N?
4) Załóżmy, że chcemy zwiększyć liczbę słów, dodając jedno słowo o długości L, a następnie musimy zmniejszyć L + 1 razy dowolne poprzednie słowo o jedno „v”. Przykład: „… * Vvvv * Vvvv * Vvvv * Vvvv” -> „… * Vvv * Vvv * Vvv * Vvv * Vvv”
Jaka jest optymalna długość słowa L?
(5 * 5 * 5 * 5 * 5) <(4 * 4 * 4 * 4 * 4) * 4, (4 * 4 * 4 * 4)> (3 * 3 * 3 * 3) * 3
=> Optymalne jest L = 4.
5) Załóżmy, że mamy wystarczająco duże N, aby wygenerować łańcuch z wieloma słowami o długości 4, ale zostało kilka naciśnięć klawiszy; jak powinniśmy ich używać?
Jeśli pozostało 5 lub więcej: Dodaj kolejne słowo o długości 4.
Jeśli pozostało 0: Gotowe.
Jeśli pozostały 4: możemy też
a) dołącz jedno słowo o długości 3: 4 * 4 * 4 * 4 * 3 = 768.
b) lub zwiększ 4 słowa do długości 5: 5 * 5 * 5 * 5 = 625. => Lepiej jest dołączyć jedno słowo.
Jeśli pozostały 3: możemy też
a) lub dołącz jedno słowo o długości 3, dostosowując poprzednie słowo od długości 4 do 3: 4 * 4 * 4 * 2 = 128 <4 * 4 * 3 * 3 = 144.
b) zwiększ 3 słowa do długości 5: 5 * 5 * 5 = 125. => Lepiej jest dołączyć jedno słowo.
Jeśli pozostały 2: możemy też
a) lub dołącz jedno słowo o długości 3, dostosowując poprzednie dwa słowa od długości 4 do 3: 4 * 4 * 1 = 16 <3 * 3 * 3 = 27.
b) zwiększ 2 słowa do długości 5: 5 * 5 = 25. => Lepiej jest dołączyć jedno słowo.
Jeśli zostanie 1: możemy też
a) lub dołącz jedno słowo o długości 3, dostosowując poprzednie trzy słowa od długości 4 do 3: 4 * 4 * 4 * 0 = 0 <3 * 3 * 3 * 3 = 81.
b) dodać jedno słowo do długości 5: 4 * 4 * 5 = 80. => Lepiej jest dołączyć jedno słowo.
6) A co, jeśli nie mamy „wystarczająco dużego N”, aby zastosować reguły z 5)? Musimy trzymać się planu b), jeśli to możliwe! Ciągi dla małego N to:
1: „v”, 2: „vv”, 3: „vvv”, 4: „vvvv”
5: „vvvvv” → 5 (plan b)
6: „vvvvvv” → 6 (plan b)
7: „vvv * Vvv” → 9 (plan a)
8: „vvvv * Vvv” → 12 (plan a)
9: „vvvv * Vvvv” → 16
10: „vvvv * Vvvvv” → 20 (plan b)
11: „vvv * Vvv * Vvv” → 29 (plan a)
12: „vvvv * Vvv * Vvv” → 36 (plan a)
13: „vvvv * Vvvv * Vvv” → 48 (plan a)
14: „vvvv * Vvvv * Vvvv” → 64
15: „vvv * Vvv * Vvv * Vvv” → 81 (plan a)
…
7) Jaka jest optymalna liczba K słów w ciągu o długości N?
Jeśli N <7, to K = 1, w przeciwnym razie 6 <N <11, to K = 2; w przeciwnym razie: K = ceil ((N + 1) / 5)
Napisane w C / C ++ / Java:
int K = (N<7)?(1) : (N<11)?(2) : ((N+5)/5);
A jeśli N> 10, to liczba słów o długości 3 wyniesie: K * 5-1-N. Dzięki temu możemy obliczyć liczbę wydrukowanych As:
Jeśli N> 10, liczba As będzie: 4 ^ {N + 1-4K} · 3 ^ {5K-N-1}
źródło
Używanie CtrlA+ CtrlC+ CtrlVjest zaletą dopiero po 4 'szóstkach.
Więc zrobiłbym coś takiego (w pseudo-BASIC-kodzie, ponieważ nie określiłeś żadnego właściwego języka):
Edytować
źródło
Potrzeba 3 naciśnięć klawiszy, aby podwoić liczbę As. Podwajanie ma sens tylko wtedy, gdy masz 3 lub więcej Jak już wydrukowano. Chcesz, aby ostatnie dozwolone naciśnięcie klawisza było a, CtrlVaby upewnić się, że podwajasz największą liczbę, jaką możesz, więc aby ją wyrównać, wypełnimy wszelkie dodatkowe naciśnięcia klawiszy po pierwszych trzech Jak na początku z większą liczbą As.
Edytować:
To okropne, całkowicie wyprzedziłem siebie i nie rozważałem wielu past dla każdej kopii.
Edycja 2:
Uważam, że wklejanie 3 razy jest optymalne, gdy masz wystarczająco dużo klawiszy, aby to zrobić. W 5 naciśnięciach klawiszy pomnóż liczbę As przez 4. Jest to lepsze niż mnożenie przez 3 za pomocą 4 naciśnięć klawiszy i lepsze niż mnożenie przez 5 za pomocą 6 naciśnięć klawiszy. Porównałem to, dając każdej metodzie taką samą liczbę naciśnięć klawiszy, na tyle, aby każdy z nich zakończył cykl w tym samym czasie (60), pozwalając mnożnikowi 3 na 15 cykli, mnożnikowi 4 na 12 cykli, a 5 mnożnik do 10 cykli. 3 ^ 15 = 14 348 907, 4 ^ 12 = 16 777 216 i 5 ^ 10 = 9 765 625. Jeśli pozostały tylko 4 naciśnięcia klawiszy, wykonanie mnożenia 3 jest lepsze niż wklejanie 4 razy więcej, zasadniczo sprawiając, że poprzednie 4 mnożniki stają się mnożnikiem 8. Jeśli pozostały tylko 3 naciśnięcia klawiszy, najlepszy jest mnożnik 2.
źródło
Załóżmy, że masz x znaków w schowku i x znaków w obszarze tekstowym; nazwijmy to „stanem x”.
Naciśnijmy kilka razy „Wklej” (
m-1
dla wygody oznaczam to przez ), a następnie „Zaznacz wszystko” i „Kopiuj”; po tej sekwencji dochodzimy do „stanu m * x”. Tutaj zmarnowaliśmy łącznie m + 1 naciśnięć klawiszy. Zatem asymptotyczny wzrost jest (przynajmniej) podobny do tegof^n
, gdzie f =m^(1/(m+1))
. Uważam, że jest to maksymalny możliwy asymptotyczny wzrost, chociaż nie mogę tego udowodnić (jeszcze).Wypróbowanie różnych wartości m pokazuje, że maksimum dla f uzyskuje się dla
m=4
.Skorzystajmy z następującego algorytmu:
(nie jestem pewien, czy jest optymalny).
Liczba naciśnięć A na początku wynosi 3: jeśli naciśniesz go 4 razy, stracisz możliwość podwojenia liczby A w 3 kolejnych naciśnięciach klawiszy.
Liczba naciśnięć Wklej na końcu nie przekracza 5: jeśli pozostało 6 lub więcej naciśnięć klawiszy, możesz zamiast tego użyć Wklej, Wklej, Wklej, Zaznacz wszystko, Kopiuj, Wklej.
Otrzymujemy więc następujący algorytm:
(nie jestem pewien, czy jest optymalny). Liczba znaków po wykonaniu tego jest podobna
3 * pow(4, floor((n - 6) / 5)) * (2 + (n - 1) % 5)
.Przykładowe wartości: 1,2,3,4,5,6,9,12,15,18,24,36,48,60,72,96,144,192,240,288, ...
źródło
Poniższy tekst wykorzystuje drugą edycję OP, która polega na tym, że wklejanie nie zastępuje istniejącego tekstu.
Zwróć uwagę na kilka rzeczy:
Każda rozsądna sekwencja naciśnięć klawiszy może być zatem zinterpretowana jako grupa Y oddzielonych znakami X, na przykład YYYXYXYYXY. Oznaczmy przez V (s) liczbę 'A wyprodukowanych przez ciąg s. Wtedy V (nXm) = V (n) * V (m), ponieważ X zasadniczo zastępuje każde Y w m przez V (n) 'A.
Problem kopiuj-wklej jest zatem izomorficzny z następującym problemem: „używając liczb m + 1, które sumują się do Nm, maksymalizuj ich iloczyn”. Na przykład, gdy N = 6, odpowiedź brzmi m = 1, a liczby (2,3). 6 = 2 * 3 = V (YYXYYY) = V (AA ^ A ^ C ^ V ^ V) (lub V (YYYXYY) = V (AAA ^ A ^ C ^ V).)
Możemy poczynić kilka obserwacji:
W przypadku ustalonej wartości
m
liczb do wyboru sąceil( (N-m)/(m+1) )
ifloor( (N-m)/(m+1) )
(w dowolnej kombinacji, która sprawi, że suma się sprawdzi, a dokładniej będziesz potrzebować(N-m) % (m+1)
ceils
i resztyfloor
). Dzieje się tak dlatego, gdyża < b
,(a+1)*(b-1) >= a*b
.Niestety nie widzę łatwego sposobu na znalezienie wartości
m
. Gdyby to był mój wywiad, zaproponowałbym w tym miejscu dwa rozwiązania:Opcja 1. Pętla nad wszystkimi możliwymi
m
.n log n
Rozwiązanie O ( ).Kod C ++:
Opcja 2. Pozwól
m
uzyskać wartości niecałkowite i znajdź jej optymalną wartość, biorąc pochodną funkcji[(N-m)/(m+1)]^m
względemm
i rozwiązując jej pierwiastek. Nie ma rozwiązania analitycznego, ale korzeń można znaleźć np. Metodą Newtona. Następnie użyj podłogi i sufitu tego pierwiastka jako wartościm
i wybierz najlepszą z nich.źródło
źródło
Oto moje podejście i rozwiązanie z kodem poniżej.
Podejście:
Można wykonać trzy różne operacje.
Teraz, biorąc pod uwagę trzy różne operacje i ich odpowiednie wyniki, musimy przejść przez wszystkie permutacje tych operacji.
Założenie:
Teraz w niektórych wersjach tego problemu stwierdza się, że sekwencja naciśnięć klawiszy, Ctrl + A -> Ctrl + C -> Ctrl + V, nadpisuje podświetlony wybór. Aby uwzględnić to założenie, wystarczy dodać tylko jedną linię kodu do poniższego rozwiązania, w którym drukowana zmienna w przypadku 2 jest ustawiona na 0
Do tego rozwiązania
Poniższy kod wypisze kilka sekwencji, a ostatnia sekwencja jest poprawną odpowiedzią dla dowolnego podanego N. np. Dla N = 11 będzie to poprawna sekwencja
Z założeniem
A, A, A, A, A, C, S, V, V, V, V,: 20:
Bez założenia
A, A, A, C, S, V, V, C, S, V, V,: 27:
Legenda klawiszy:
„A” - A
„C” - Ctrl + A
„S” - Ctrl + C
„V” - Ctrl + V
Kod:
źródło
Korzystając ze sztuczek wymienionych w odpowiedziach powyżej, Matematycznie rozwiązanie można wyjaśnić w jednym równaniu jako,
4 + 4 ^ [(N-4) / 5] + ((N-4)% 5) * 4 ^ [(N-4) / 5]. gdzie [] jest największym współczynnikiem całkowitym
źródło
Istnieje kompromis między ręcznym drukowaniem mA, a następnie użyciem Ctrl+ A, Ctrl+ Ci Nm-2 Ctrl+ V. Najlepsze rozwiązanie znajduje się pośrodku. Jeśli maksymalna liczba naciśnięć klawiszy = 10, najlepszym rozwiązaniem jest wpisanie 5 lub 4 liter.
spróbuj użyć tego Spójrz na http://www.geeksforgeeks.org/how-to-print-maximum-number-of-a-using-given-four-keys/ i może trochę zoptymalizuj, szukając wyników mniej więcej w połowie punkt.
źródło
Oto moje rozwiązanie z programowaniem dynamicznym, bez zagnieżdżonej pętli, które również drukuje rzeczywiste znaki, które trzeba wpisać:
To jest wynik („a” oznacza „CTRL + A” itp.)
źródło
Jeśli dozwolonych jest N uderzeń klawisza, wynikiem jest N-3.
A's -> N-3
CTRL+ A-> Wybieranie tych znaków N: +1
CTRL+ C-> Kopiowanie tych znaków N: +1
Ctrl+ V-> Wklejanie znaków N. : +1 tj. (Ponieważ wybraliśmy całe znaki za pomocą CTRL+ A) Zastąpienie tych istniejących N-3 znaków skopiowanymi N-3 Znakami (które zastępują te same znaki) i wynikiem jest N-3.
źródło
→
. Poprawi to czytelność Twojej odpowiedzi!