Dies ist eine Interviewfrage von Google. Ich kann es nicht alleine lösen. Kann jemand etwas Licht ins Dunkel bringen?
Schreiben Sie ein Programm, um die Folge von Tastenanschlägen so zu drucken, dass die maximale Anzahl von Zeichen 'A' generiert wird. Sie dürfen nur 4 Tasten verwenden : A, Ctrl+ A, Ctrl+ Cund Ctrl+ V. Es sind nur N Tastenanschläge zulässig. Alle Ctrl+ Zeichen werden als ein Tastendruck betrachtet, also ist Ctrl+ Aein Tastendruck.
Zum Beispiel kann die Sequenz A, Ctrl+ A, Ctrl+ C, Ctrl+ Verzeugt zwei A die in 4 Tastenanschlägen.
- Strg + A ist Alle auswählen
- Strg + C ist Kopieren
- Strg + V ist Einfügen
Ich habe etwas Mathematik gemacht. Für jedes N können wir mit x Zahlen von A, eins Ctrl+ A, eins Ctrl+ Cund y Ctrl+ Veine maximale ((N-1) / 2) 2 Anzahl von A erzeugen . Für einige N> M ist es besser, so viele Ctrl+ A, Ctrl+ Cund Ctrl+ VSequenzen zu verwenden, wie die Anzahl der A verdoppelt.
Die Sequenz Ctrl+ A, Ctrl+ V, Ctrl+ Cüberschreibt die vorhandene Auswahl nicht. Die kopierte Auswahl wird an die ausgewählte angehängt.
^A
ist normalerweise "Alles auswählen",^C
"Kopieren",^V
"Einfügen". Gibt Ihnen das eine Idee?Antworten:
Es gibt eine dynamische Programmierlösung. Wir beginnen damit zu wissen, dass 0 Schlüssel uns zu 0 A machen können. Dann durchlaufen wir
i
bis zun
zwei Dinge: Drücken Sie einmal A und drücken Sie Auswahl alle + Kopieren, gefolgt von Einfügezeitenj
(siehej-i-1
unten; beachten Sie den Trick hier: Der Inhalt befindet sich noch in der Zwischenablage, sodass wir ihn mehrmals ohne Einfügen einfügen können jedes Mal kopieren). Wir müssen nur bis zu 4 aufeinanderfolgende Pasten berücksichtigen, da Auswählen, Kopieren, Einfügen x 5 dem Auswählen, Kopieren, Einfügen, Auswählen, Kopieren, Einfügen entspricht. Letzteres ist besser, da wir mehr in der Zwischenablage haben. Sobald wir erreicht habenn
, haben wir das gewünschte Ergebnis.Die Komplexität scheint O (N) zu sein, aber da die Zahlen exponentiell wachsen, ist sie aufgrund der Komplexität der Multiplikation der großen Zahlen tatsächlich O (N 2 ). Unten finden Sie eine Python-Implementierung. Die Berechnung für N = 50.000 dauert ungefähr 0,5 Sekunden.
Stellt im Code
j
die Gesamtzahl der Tasten dar, die nach unserer neuen Tastenfolge gedrückt wurden. Zui
diesem Zeitpunkt haben wir bereits Tastendrücke, und zwei neue Tastendrücke werden ausgewählt und kopiert. Deshalb treffen wir Einfügezeitenj-i-2
. Da Einfügen in die bestehende Sequenz von fügtdp[i]
A
ist, müssen wir hinzufügen ,1
so dass esj-i-1
. Dies erklärt dasj-i-1
in der vorletzten Zeile.Hier sind einige Ergebnisse (
n
=> Anzahl der A):Ich stimme @SB zu, dass Sie immer Ihre Annahmen angeben sollten: Meine ist, dass Sie nicht zweimal einfügen müssen, um die Anzahl der Zeichen zu verdoppeln. Dies erhält die Antwort für 7, und wenn meine Lösung nicht falsch ist, muss die Annahme richtig sein.
Falls jemand fragt , warum ich nicht Folgen der Form Überprüfung Ctrl+ A, Ctrl+ C, A, Ctrl+ V: Das Endergebnis wird immer das gleiche sein wie A, Ctrl+ A, Ctrl+ C, Ctrl+ , Vdie ich tue betrachten.
quelle
n => result
oderresult => n
? In jedem Fall denke ich, dass es falsch ist. Wir können 9 wie mit 7 Tastenanschlägen eingeben. Wenn es so ist, istn => result
es definitiv falsch. Die Anzahl der As, die Sie eingeben können, darf nicht niedriger sein alsn
.n => result
. Sie sagen "Wir können 9 wie mit 7 Tastenanschlägen eingeben", was ich bekomme. Lesen Sie den "Trick", den ich gerade bearbeitet habe.n
ist der Tastenanschlag, den Sie verwenden dürfen. Sie müssen berechnen, wie viele Sie mitn
Tastenanschlägen eingeben können. Macht also7 => 7
keinen Sinn.O(n)
oder sogarO(1)
:).Durch die Verwendung von Marcogs Lösung habe ich ein Muster gefunden, das bei beginnt
n=16
. Um dies zu verdeutlichen sind hier die Tastenanschläge fürn=24
bis zun=29
, ich ersetzt ^ A mit S (wählen), ^ C mit C (kopieren) und ^ V mit P (Paste) zur besseren Lesbarkeit:Nach einer anfänglichen 4 As ist das ideale Muster zum Auswählen, Kopieren, Einfügen, Einfügen, Einfügen und Wiederholen. Dies multipliziert die Anzahl von As mit 4 alle 5 Tastenanschläge. Wenn dieses 5-Tasten-Muster die verbleibenden Tastenanschläge nicht alleine verbrauchen kann, verbrauchen einige 4-Tasten-Muster (SCPP) die letzten Tastenanschläge und ersetzen SCPPP (oder entfernen eine der Pasten) nach Bedarf. Die 4 Tastenanschläge multiplizieren die Summe mit 3 alle 4 Tastenanschläge.
Bei Verwendung dieses Musters handelt es sich um Python-Code, der die gleichen Ergebnisse wie die Lösung von marcog erzielt, jedoch O (1) bearbeitet : Dies ist tatsächlich O (log n) aufgrund von Potenzierung, danke an IVlad für den Hinweis.
Berechnung von e3: Am Ende der Tastenanschlagliste stehen immer zwischen 0 und 4 SCPP-Muster, denn
n % 5 == 4
es gibt 4,n % 5 == 1
es gibt 3,n % 5 == 2
es gibt 2,n % 5 == 3
es gibt 1 undn % 5 == 4
es gibt 0. Dies kann vereinfacht werden(4 - n) % 5
.Berechnung von e4: Die Gesamtzahl der Muster erhöht sich jedes Mal um 1
n % 5 == 0
, wie sich herausstellt, erhöht sich diese Anzahl auf genaun / 5
. Mit der Bodenteilung können wir die Gesamtzahl der Muster erhalten, die Gesamtzahl füre4
ist die Gesamtzahl der Muster minuse3
. Für diejenigen, die mit Python nicht vertraut sind,//
ist die zukunftssichere Notation für die Bodenteilung.quelle
n=3000
, also ist es wahrscheinlich richtig. (Schade, dass ich heuteO(1)
so, dass die Potenzierung nicht in konstanter Zeit erfolgen kann. Es istO(log n)
.So würde ich es angehen:
Bei einem bestimmten Text sind 4 Tastenanschläge erforderlich, um ihn zu duplizieren:
Von dort aus können Sie 4 oder 5 A machen und dann die obigen Schritte durchlaufen. Beachten Sie, dass
ctrl + a, c, v, v
Ihr Text beim Durchlaufen exponentiell wächst. Wenn die verbleibenden Striche <4 sind, machen Sie einfach weiter aCtrlVDer Schlüssel zu Interviews an Orten wie Google besteht darin, Ihre Annahmen anzugeben und Ihr Denken zu kommunizieren. Sie wollen wissen, wie Sie Probleme lösen.
quelle
ACVV-VVVVV
multipliziert mit 7,ACVV-ACVV-V
multipliziert mit 6. Also Strg-V für verbleibende Striche <6 statt 4.Es ist in O (1) lösbar: Wie bei den Fibonacci-Zahlen gibt es eine Formel zur Berechnung der Anzahl der gedruckten As (und der Reihenfolge der Tastenanschläge):
1) Wir können die Problembeschreibung vereinfachen:
gleich
2) Wir können die Folge von Tastenanschlägen als eine Folge von N Zeichen aus {'*', 'V', 'v'} beschreiben, wobei 'v' [Cv] und '*' [Ca] und 'V bedeutet 'bedeutet [Cc]. Beispiel: "vvvv * Vvvvv * Vvvv"
Die Länge dieser Zeichenfolge entspricht immer noch N.
Das Produkt der Längen der Vv-Wörter in dieser Zeichenfolge entspricht der Anzahl der produzierten As.
3) Bei einer festen Länge N für diese Zeichenfolge und einer festen Anzahl K von Wörtern ist das Ergebnis maximal, wenn alle Wörter nahezu gleich lang sind. Ihr paarweiser Unterschied beträgt nicht mehr als ± 1.
Was ist nun die optimale Zahl K, wenn N gegeben ist?
4) Angenommen, wir möchten die Anzahl der Wörter erhöhen, indem wir ein einzelnes Wort der Länge L anhängen. Dann müssen wir L + 1-mal jedes vorherige Wort um ein 'v' reduzieren. Beispiel: "... * Vvvv * Vvvv * Vvvv * Vvvv" -> "... * Vvv * Vvv * Vvv * Vvv * Vvv"
Was ist nun die optimale Wortlänge L?
(5 * 5 * 5 * 5 * 5) <(4 * 4 * 4 * 4 * 4) * 4, (4 * 4 * 4 * 4)> (3 * 3 * 3 * 3) * 3
=> Optimal ist L = 4.
5) Angenommen, wir haben ein ausreichend großes N, um eine Zeichenfolge mit vielen Wörtern der Länge 4 zu erzeugen, aber es bleiben einige Tastenanschläge übrig. Wie sollen wir sie verwenden?
Wenn noch 5 oder mehr übrig sind: Fügen Sie ein weiteres Wort mit der Länge 4 hinzu.
Wenn noch 0 übrig sind: Fertig.
Wenn noch 4 übrig sind: Wir könnten es auch
a) Fügen Sie ein Wort mit der Länge 3: 4 * 4 * 4 * 4 * 3 = 768 hinzu.
b) oder erhöhen Sie 4 Wörter auf Länge 5: 5 * 5 * 5 * 5 = 625. => Ein Wort anzuhängen ist besser.
Wenn noch 3 übrig sind: Wir könnten es auch
a) oder fügen Sie ein Wort mit der Länge 3 hinzu, indem Sie das vorherige Wort von Länge 4 auf 3 einstellen: 4 * 4 * 4 * 2 = 128 <4 * 4 * 3 * 3 = 144.
b) Erhöhen Sie 3 Wörter auf Länge 5: 5 * 5 * 5 = 125. => Ein Wort anzuhängen ist besser.
Wenn noch 2 übrig sind: Wir könnten es auch
a) oder fügen Sie ein Wort mit der Länge 3 hinzu, indem Sie die vorherigen zwei Wörter von der Länge 4 auf 3 einstellen: 4 * 4 * 1 = 16 <3 * 3 * 3 = 27.
b) Erhöhen Sie 2 Wörter auf Länge 5: 5 * 5 = 25. => Ein Wort anzuhängen ist besser.
Wenn noch 1 übrig ist: Wir könnten es auch
a) oder fügen Sie ein Wort mit der Länge 3 hinzu, indem Sie die vorherigen drei Wörter von Länge 4 auf 3 einstellen: 4 * 4 * 4 * 0 = 0 <3 * 3 * 3 * 3 = 81.
b) Erhöhen Sie ein Wort auf Länge 5: 4 * 4 * 5 = 80. => Ein Wort anzuhängen ist besser.
6) Was ist nun, wenn wir kein "ausreichend großes N" haben, um die Regeln in 5) zu verwenden? Wir müssen uns an Plan b) halten, wenn möglich! Die Zeichenfolgen für kleines N sind:
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) Was ist nun die optimale Anzahl K von Wörtern in einer Zeichenfolge der Länge N?
Wenn N <7, dann ist K = 1, sonst wenn 6 <N <11, dann ist K = 2; sonst: K = Ceil ((N + 1) / 5)
Geschrieben in C / C ++ / Java:
int K = (N<7)?(1) : (N<11)?(2) : ((N+5)/5);
Und wenn N> 10 ist, ist die Anzahl der Wörter mit der Länge 3: K * 5-1-N. Damit können wir die Anzahl der gedruckten As berechnen:
Wenn N> 10 ist, ist die Anzahl von As: 4 ^ {N + 1-4K} · 3 ^ {5K-N-1}
quelle
Die Verwendung von CtrlA+ CtrlC+ CtrlVist erst nach 4 'A von Vorteil.
Also würde ich so etwas machen (im Pseudo-BASIC-Code, da Sie keine richtige Sprache angegeben haben):
Bearbeiten
quelle
Es sind 3 Tastenanschläge erforderlich, um die Anzahl der As zu verdoppeln. Es ist nur sinnvoll, mit dem Verdoppeln zu beginnen, wenn Sie 3 oder mehr wie bereits gedruckt haben. Sie möchten, dass Ihr letzter zulässiger Tastenanschlag ein ist CtrlV, um sicherzustellen, dass Sie die größtmögliche Zahl verdoppeln. Um ihn auszurichten, füllen wir nach den ersten drei As am Anfang alle zusätzlichen Tastenanschläge mit mehr As aus.
Bearbeiten:
Das ist schrecklich, ich habe mich selbst völlig übertroffen und nicht mehrere Pasten für jede Kopie in Betracht gezogen.
Bearbeiten 2:
Ich glaube, 3-maliges Einfügen ist optimal, wenn Sie genug Tastenanschläge haben, um dies zu tun. In 5 Tastenanschlägen multiplizieren Sie Ihre Anzahl von As mit 4. Dies ist besser als das Multiplizieren mit 3 mit 4 Tastenanschlägen und besser als das Multiplizieren mit 5 mit 6 Tastenanschlägen. Ich verglich dies, indem ich jeder Methode die gleiche Anzahl von Tastenanschlägen gab, so dass jeder zur gleichen Zeit einen Zyklus beendete (60), wobei der 3-Multiplikator 15 Zyklen, der 4-Multiplikator 12 Zyklen und der 5-Multiplikator ausführen ließ. Multiplikator machen 10 Zyklen. 3 ^ 15 = 14.348.907, 4 ^ 12 = 16.777.216 und 5 ^ 10 = 9.765.625. Wenn nur noch 4 Tastenanschläge übrig sind, ist es besser, einen 3-Multiplikator auszuführen, als 4 weitere Male einzufügen, wodurch der vorherige 4-Multiplikator im Wesentlichen zu einem 8-Multiplikator wird. Wenn nur noch 3 Tastenanschläge übrig sind, ist ein 2-Multiplikator am besten.
quelle
Angenommen, Sie haben x Zeichen in der Zwischenablage und x Zeichen im Textbereich. Nennen wir es "Zustand x".
Drücken wir ein paar Mal auf "Einfügen" (ich bezeichne es der Einfachheit
m-1
halber mit), dann auf "Alles auswählen" und "Kopieren". Nach dieser Sequenz gelangen wir zum "Zustand m * x". Hier haben wir insgesamt m + 1 Tastenanschläge verschwendet. Das asymptotische Wachstum ist also (zumindest) so etwas wief^n
f =m^(1/(m+1))
. Ich glaube, es ist das maximal mögliche asymptotische Wachstum, obwohl ich es (noch) nicht beweisen kann.Das Ausprobieren verschiedener Werte von m zeigt, dass das Maximum für f für erhalten wird
m=4
.Verwenden wir den folgenden Algorithmus:
(nicht sicher, ob es das optimale ist).
Die Häufigkeit, mit der A zu Beginn gedrückt wird, beträgt 3: Wenn Sie 4 Mal drücken, verpassen Sie die Gelegenheit, die Anzahl der A in 3 weiteren Tastenanschlägen zu verdoppeln.
Das Drücken von Einfügen am Ende beträgt höchstens 5: Wenn Sie noch 6 oder mehr Tastenanschläge haben, können Sie stattdessen Einfügen, Einfügen, Einfügen, Alles auswählen, Kopieren, Einfügen verwenden.
Wir erhalten also den folgenden Algorithmus:
(nicht sicher, ob es das optimale ist). Die Anzahl der Zeichen nach der Ausführung ist ungefähr so
3 * pow(4, floor((n - 6) / 5)) * (2 + (n - 1) % 5)
.Stichprobenwerte: 1,2,3,4,5,6,9,12,15,18,24,36,48,60,72,96,144,192,240,288, ...
quelle
Im Folgenden wird die zweite Bearbeitung des OP verwendet, bei der das Einfügen vorhandenen Text nicht ersetzt.
Beachten Sie einige Dinge:
Jede vernünftige Tastenfolge kann somit als eine durch X getrennte Gruppe von Ys interpretiert werden, beispielsweise YYYXYXYYXY. Bezeichne mit V (s) die Anzahl von 'A', die durch die Sequenz s erzeugt werden. Dann ist V (nXm) = V (n) * V (m), weil X im Wesentlichen jedes Y in m durch V (n) 'A ersetzt.
Das Copy-Paste-Problem ist daher isomorph zu dem folgenden Problem: "Verwenden von m + 1-Zahlen, die sich zu Nm summieren, maximieren Sie ihr Produkt." Wenn beispielsweise N = 6 ist, lautet die Antwort m = 1 und die Zahlen (2,3). 6 = 2 · 3 = V (JJJJJ) = V (AA ^ A ^ C ^ V ^ V) (oder V (JJJXJJ) = V (AAA ^ A ^ C ^ V).)
Wir können einige Beobachtungen machen:
Für einen festen Wert von
m
sind die zu wählenden Zahlenceil( (N-m)/(m+1) )
undfloor( (N-m)/(m+1) )
(in welcher Kombination auch immer die Summe funktioniert; genauer gesagt, Sie benötigen(N-m) % (m+1)
ceils
und die restlichenfloor
s). Dies liegt daran, dass za < b
.(a+1)*(b-1) >= a*b
.Leider sehe ich keinen einfachen Weg, um den Wert von zu finden
m
. Wenn dies mein Interview wäre, würde ich an dieser Stelle zwei Lösungen vorschlagen:Option 1. Alle möglichen Schleifen durchlaufen
m
. Eine O (n log n
) -Lösung.C ++ - Code:
Option 2. Erlauben Sie
m
, nicht ganzzahlige Werte zu erreichen und den optimalen Wert zu finden, indem Sie die Ableitung von[(N-m)/(m+1)]^m
in Bezug aufm
die Wurzel nehmen und nach dieser suchen . Es gibt keine analytische Lösung, aber die Wurzel kann beispielsweise mit der Newtonschen Methode gefunden werden. Verwenden Sie dann den Boden und die Decke dieser Wurzel für den Wert vonm
und wählen Sie die beste aus.quelle
quelle
Hier ist mein Ansatz und meine Lösung mit dem folgenden Code.
Ansatz:
Es gibt drei verschiedene Operationen, die ausgeführt werden können.
Angesichts der drei unterschiedlichen Operationen und ihrer jeweiligen Ausgaben müssen wir nun alle Permutationen dieser Operationen durchlaufen.
Annahme:
In einer Version dieses Problems heißt es nun, dass die Tastenfolge Strg + A -> Strg + C -> Strg + V die hervorgehobene Auswahl überschreibt. Um diese Annahme zu berücksichtigen, muss der folgenden Lösung nur eine Codezeile hinzugefügt werden, in der die gedruckte Variable in Fall 2 auf 0 gesetzt ist
Für diese Lösung
Der folgende Code gibt einige Sequenzen aus und die letzte Sequenz ist die richtige Antwort für jedes gegebene N. ZB für N = 11 ist dies die richtige Sequenz
Mit der Annahme
A, A, A, A, A, C, S, V, V, V, V: 20:
Ohne die Annahme
A, A, A, C, S, V, V, C, S, V, V: 27:
Tastenanschlag-Legende:
'A' - A.
'C' - Strg + A.
'S' - Strg + C.
'V' - Strg + V.
Code:
quelle
Unter Verwendung der in den obigen Antworten genannten Tricks kann die Lösung mathematisch in einer Gleichung wie folgt erklärt werden:
4 + 4 ^ [(N-4) / 5] + ((N-4)% 5) * 4 ^ [(N-4) / 5]. Dabei ist [] der größte ganzzahlige Faktor
quelle
Es gibt einen Kompromiss zwischen dem manuellen Drucken von mA und der Verwendung von Ctrl+ A, Ctrl+ Cund Nm-2 Ctrl+ V. Die beste Lösung ist in der Mitte. Wenn max. Tastenanschläge = 10 sind, ist die beste Lösung die Eingabe von 5 A oder 4 A.
Versuchen Sie es mit diesem Look. Schauen Sie sich diesen http://www.geeksforgeeks.org/how-to-print-maximum-number-of-a-using-given-four-keys/ an und optimieren Sie möglicherweise ein wenig, um nach den Ergebnissen in der Mitte zu suchen Punkt.
quelle
Hier ist meine Lösung mit dynamischer Programmierung ohne verschachtelte Schleife, die auch die tatsächlichen Zeichen druckt, die Sie eingeben müssen:
Dies ist die Ausgabe ('a' bedeutet 'STRG + A' usw.)
quelle
Wenn N Tastenanschläge zulässig sind, ist das Ergebnis N-3.
A's -> N-3
CTRL+ A-> Auswahl dieser N Zeichen: +1
CTRL+ C-> Kopieren dieser N Zeichen: +1
Ctrl+ V-> Einfügen der N Zeichen. : +1 dh (Da wir die gesamten Zeichen mit CTRL+ ausgewählt haben A) Ersetzen dieser vorhandenen N-3-Zeichen durch die kopierten N-3-Zeichen (die dieselben Zeichen überschreiben) und das Ergebnis ist N-3.
quelle
→
. Dies verbessert die Lesbarkeit Ihrer Antwort!