3 Möglichkeiten zur Verbesserung Ihrer Coding-Interview-Lösung

3 Möglichkeiten zur Steigerung der Effizienz Ihrer Coding-Interview-Lösung

Da bist du also. Erleichtert. Erschöpft. Sie haben endlich einen Ansatz gefunden, um die knifflige Codierungsfrage zu lösen, die Ihr Interviewer Ihnen stellt. Vielleicht haben Sie es sogar Zeile für Zeile auf das Whiteboard geschrieben. Und du hast gute Zeit gemacht! Sie sind nur 20 Minuten in der Besprechung. Ihr Interviewer muss beeindruckt sein.

Recht?

„Das wird funktionieren, aber gibt es Ideen, wie man es effizienter macht?“

Dein Herz sinkt. Sie dachten, Sie wären mit dem kniffligen Teil des Algorithmus-Designs fertig! Sie versuchen, mehr Möglichkeiten zur Lösung des Problems zu finden, aber Sie können sich nur den einen Ansatz vorstellen, den Sie sich bereits ausgedacht haben.

Das passiert fast jedem. Und es ist nicht, weil sie dumm sind. Dies liegt daran, dass die meisten Menschen keine Methode zur Verbesserung der Effizienz ihrer Algorithmen haben.

Aber die Wahrheit ist, es gibt viele. Wenn Sie das nächste Mal ratlos sind, versuchen Sie, diese drei gängigen Ansätze anzuwenden.

1. Verwenden Sie eine Hash Map

Das stimmt. Hash-Maps / assoziative Arrays / Wörterbücher (sie haben viele Namen, je nachdem, welche Programmiersprache Sie verwenden) haben eine magische Fähigkeit, die Laufzeit von Algorithmen zu verkürzen.

Angenommen, die Frage bestand darin, die am häufigsten wiederholte Zahl in einem Array von Zahlen zu finden.

Ihr erster Gedanke könnte sein, in einige Schleifen zu springen. Finden Sie für jede unserer Zahlen die Anzahl heraus und prüfen Sie, ob es die größte ist. Wie erhalten wir die Zählung für jede Nummer? Durchlaufen Sie das Array und zählen Sie, wie oft es auftritt! Wir sprechen also von zwei verschachtelten Schleifen. Im Pseudocode:

def get_mode (nums): max_count = 0 mode = null für Potentialmodus in nums: count = 0 für number in our_array: count + = 1 wenn count> = max_count: mode = potentieller_modus max_count = count return mode 

Im Moment durchlaufen wir unser gesamtes Array einmal für jedes Element im Array – aber wir können es besser machen. In der großen O-Notation ist das O (n 2) ).

Wenn wir unsere Zählungen in einer Hash-Map speichern (indem wir die Zahlen ihren Zählungen zuordnen), können wir das Problem in nur einem Schritt durch das Array lösen (O (n) Zeit!):

def get_mode (nums): max_count = 0 mode = null zählt = neue HashMap, wobei jeder Wert bei 0 für potentieller Modus in nums beginnt: zählt [potentieller Modus] + = 1, wenn zählt [potentieller Modus]> max_count: mode = potentieller Modus max_count = zählt [potentieller Modus ] Rückgabemodus 

Viel schneller!

2. Verwenden Sie die Bitmanipulation

Dies wird Sie wirklich von der Masse abheben. Es trifft nicht auf jedes Problem zu, aber wenn Sie dies in Ihrer Gesäßtasche aufbewahren und zum richtigen Zeitpunkt herausspringen lassen, sehen Sie aus wie ein Rockstar.

Hier ein Beispiel: Angenommen, wir hatten ein Array von Zahlen, bei denen jede Zahl zweimal vorkommt, mit Ausnahme einer Zahl, die nur einmal vorkommt. Wir schreiben eine Funktion, um die einsame, nicht wiederholte Nummer zu finden.

Ihr erster Instinkt könnte darin bestehen, eine Hash-Map zu verwenden, da wir gerade darüber gesprochen haben. Das ist ein guter Instinkt! Und es wird für diesen funktionieren. Wir können eine sehr ähnliche „Zähl“ -Karte erstellen und diese verwenden, um zu sehen, welche Zahl mit einer Zählung von 1 endet.

Aber es gibt noch einen besseren Weg. Wenn Sie mit vertraut sind Bitmanipulations, könnten Sie mit vertraut sein XOR. Eine Besonderheit von XOR ist, dass, wenn Sie eine Zahl mit sich selbst XOREN, die Bits auf 0 „aufheben“. Wenn wir für dieses Problem jede Zahl im Array zusammen XOREN, bleibt die eine Zahl übrig, die dies nicht getan hat nicht aufheben:

def find_unrepeated (nums): nicht wiederholt = 0 für num in nums: nicht wiederholt = nicht wiederholt XOR num return nicht wiederholt 

3. Gehen Sie von unten nach oben

Schreiben Sie eine Funktion, die die „n-te“ Fibonacci-Zahl mit einer Zahl n ausgibt. Dies ist ein Klassiker, und es eignet sich sehr gut für die Rekursion:

def fib (n): wenn n 0 oder 1 ist: return 1 return fib (n-1) + fib (n-2) 

Aber die einfache rekursive Antwort ist nicht die einzige! Überlegen Sie genau, was diese Funktion bewirkt. Angenommen, n ist 5. Um die Antwort zu erhalten, werden rekursiv fib (4) und fib (3) aufgerufen. Was bewirkt dieser Aufruf von fib (4)? Es heißt fib (3) und fib (2). Aber wir haben gerade gesagt, wir hätten bereits einen Anruf bei fib (3)! Diese niedliche rekursive Funktion macht viel Wiederholungsarbeit. Die Gesamtzeitkosten betragen O (2 n ). Das ist schlecht – viel schlimmer als O (n 2 ).

Anstatt von n rekursiv nach unten zu 1 zu gehen, gehen wir von 1 nach n von unten nach oben. Dadurch können wir die Rekursion überspringen:

def fib (n): previous = 0 previous_previous = 1 für i im Bereich von 1 bis n: current = previous + previous_previous previous_previous = previous previous = aktueller Rückstrom 

Der Code ist länger, aber viel effizienter! Bis zu O (n) Zeit. Als zusätzlichen Bonus beim Abrollen rekursiver Algorithmen sparen wir Platz. Alle diese rekursiven Aufrufe werden im Aufrufstapel aufgebaut, der sich im Speicher befindet und auf unsere Platzkosten angerechnet wird. Unsere rekursive Funktion hatte O (n) Raumkosten, aber diese iterative nimmt O (1) Raum in Anspruch.

Wenn Ihr Interviewer Sie das nächste Mal auffordert, die Effizienz Ihrer Lösung zu verbessern, versuchen Sie, diese Strategien durchzugehen und zu prüfen, ob sie helfen. Mit genügend Übung werden Sie wahrscheinlich direkt zur optimierten Lösung springen und die naivere Lösung überspringen. Und das ist eine großartige Sache. Es bedeutet nicht nur, dass Sie ein besserer Interviewer werden – es bedeutet, dass Sie ein besserer Ingenieur werden.