Verstehen der Prinzipien des Algorithmusdesigns

Dieser Artikel befasst sich mit den Prinzipien des Algorithmusentwurfs. Wenn Sie keine Ahnung haben, worauf ich mich beziehe, lesen Sie weiter!

Wenn Sie das Wort "Algorithmus" hören, antworten Sie wahrscheinlich auf eine von drei Arten:

  1. Sie wissen sofort und verstehen, worüber wir sprechen, weil Sie Informatik studiert haben.
  2. Sie wissen, dass Algorithmen die Arbeitspferde von Unternehmen wie Google und Facebook sind, aber Sie wissen nicht genau, was das Wort bedeutet.
  3. Sie laufen und verstecken sich in Angst, denn alles, was Sie über Algorithmen wissen, erinnert Sie an Calculus Albträume der High School.

Wenn Sie einer der zweiten beiden sind, ist dieser Artikel für Sie.


Was ist genau ein Algorithmus??

Algorithmen sind nicht unbedingt eine besondere Art von Operation. Sie sind konzeptionell, eine Reihe von Schritten, die Sie im Code ausführen, um ein bestimmtes Ziel zu erreichen.

Algorithmen wurden allgemein in einfachen Worten als "Anweisungen zum Erfüllen einer Aufgabe" definiert. Sie wurden auch "Rezepte" genannt. Im Das soziale Netzwerk, Zuckerberg brauchte einen Algorithmus, damit Facemash funktioniert. Wenn Sie den Film gesehen haben, erinnern Sie sich wahrscheinlich daran, wie eine kritzelnde Gleichung auf einem Fenster in Marks Schlafsaal aussah. Aber was hat diese kritzelnde Algebra mit Marks einfacher "heißer" oder "nicht" -Seite zu tun??

Algorithmen sind in der Tat Anweisungen. Eine genauere Beschreibung wäre vielleicht, dass Algorithmen Muster sind, um eine Aufgabe auf effiziente Weise abzuschließen. Zuckerbergs Facemash war ein Abstimmungsort, um die Attraktivität einer Person im Verhältnis zu einer ganzen Gruppe von Personen zu bestimmen, aber dem Benutzer würden nur Optionen zwischen zwei Personen gegeben. Mark Zuckerberg brauchte einen Algorithmus, mit dem festgelegt wurde, welche Personen miteinander verglichen werden sollten und wie eine Stimme relativ zur Vorgeschichte dieser Person und zu den früheren Konkurrenten bewertet werden sollte. Dies erforderte mehr Intuition als einfach das Stimmenzählen für jede Person.

Angenommen, Sie wollten einen Algorithmus erstellen, um 1 zu einer negativen Zahl zu addieren und 1 von einer positiven Zahl zu subtrahieren und nichts zu 0 zu machen. Sie könnten etwa Folgendes tun (im JavaScript-artigen Pseudocode):

function addOrSubtractOne (number) if (number.) < 0)  return number + 1  else if (number < 0)  return number - 1  else if (number == 0)  return 0;  

Sie können zu sich selbst sagen: "Das ist eine Funktion." Und du hast recht. Algorithmen sind nicht unbedingt eine besondere Art von Operation. Sie sind konzeptionell - eine Reihe von Schritten, die Sie im Code ausführen, um ein bestimmtes Ziel zu erreichen.

Warum sind sie eine große Sache? Das Hinzufügen oder Abziehen von 1 zu einer Zahl ist ganz einfach.

Aber lassen Sie uns kurz über das Suchen sprechen. Wie würden Sie Ihrer Meinung nach nach einer Zahl in einem Zahlenfeld suchen? Ein naiver Ansatz wäre, die Zahl zu iterieren und jede Zahl mit der gesuchten Zahl zu vergleichen. Dies ist jedoch keine effiziente Lösung und bietet einen sehr großen Bereich möglicher Ausführungszeiten, was es zu einer unberechenbaren und unzuverlässigen Suchmethode macht, wenn es auf große Suchmengen skaliert wird.

Funktion naiveSearch (Nadel, Heuhaufen) für (var i = 0; i < haystack.length; i++) if (haystack[i] == needle)  return needle;   return false; 

Glücklicherweise können wir für die Suche mehr tun.

Warum ist es ineffizient??

Es gibt keinen besseren Weg, ein besserer Algorithmus-Designer zu werden, als ein tiefes Verständnis und Verständnis für Algorithmen zu haben.

Nehmen wir an, Ihr Array hat 50.000 Einträge, und Sie suchen brutal (dh, indem Sie das gesamte Array iterieren). Der Eintrag, den Sie suchen, ist im besten Fall der erste Eintrag in dem Feld mit 50.000 Einträgen. Im schlimmsten Fall dauert der Algorithmus jedoch 50.000 Mal länger als im besten Fall.

Was ist besser??

Stattdessen würden Sie die binäre Suche verwenden. Dies umfasst das Sortieren des Arrays (worüber ich Sie selbst informieren kann) und anschließend das Array in zwei Hälften teilen und überprüfen, ob die Suchnummer größer oder kleiner als die Halbmarkierung im Array ist. Wenn sie größer ist als die Halbmarke eines sortierten Arrays, wissen wir, dass die erste Hälfte verworfen werden kann, da die gesuchte Zahl nicht Teil des Arrays ist. Wir können auch eine Menge Arbeit abschneiden, indem wir die äußeren Grenzen des Arrays definieren und prüfen, ob die gesuchte Nummer außerhalb dieser Grenzen vorhanden ist. Wenn ja, haben wir eine Operation mit mehreren Iterationen genommen und diese gedreht in eine einzige Iterationsoperation (die im Brute-Force-Algorithmus 50.000 Operationen erfordert hätte).

sortiertesHaystack = rekursivesSort (Heuhaufen); Funktion bSearch (Nadel, sortierterHaystack, firstIteration) if (firstIteration) if (Nadel> sortierterHaystack.last || Nadel < sortedHaystack.first) return false;   if (haystack.length == 2) if (needle == haystack[0])  return haystack[0];  else  return haystack[1];   if (needle < haystack[haystack.length/2]) bSearch(needle, haystack[0… haystack.length/2 -1], false);  else  bSearch(needle, haystack[haystack.length/2… haystack.length], false);  

Klingt ziemlich kompliziert

Nehmen Sie die scheinbar komplizierte Natur eines einzelnen binären Suchalgorithmus an und wenden Sie ihn auf Milliarden möglicher Links (wie bei Google) an. Darüber hinaus wenden wir eine Art Ranking-System auf diese verknüpften Suchen an, um die Reihenfolge der Antwortseiten anzugeben. Besser noch: Wenden Sie eine Art scheinbar randomisiertes "Vorschlag" -System an, das auf sozialen Modellen für künstliche Intelligenz basiert, um festzustellen, wen Sie als Freund hinzufügen möchten.

Dies verdeutlicht, warum Algorithmen mehr als nur ein ausgefallener Name für Funktionen sind. Im besten Fall sind sie clevere und effiziente Wege, etwas zu tun, das ein höheres Maß an Intuition erfordert als die scheinbarste Lösung. Es kann Jahre dauern, bis ein Supercomputer dies erledigt hat, und es kann zu einer Aufgabe werden, die auf einem Mobiltelefon innerhalb von Sekunden erledigt ist.

Wie lassen sich Algorithmen auf mich anwenden??

Für die meisten von uns als Entwickler entwerfen wir nicht täglich hochrangige abstrahierte Algorithmen.

Glücklicherweise stehen wir auf den Schultern der Entwickler, die vor uns hergekommen sind, die native Sortierfunktionen geschrieben haben, und ermöglichen es uns, Zeichenfolgen mit indexOf auf effiziente Weise zu durchsuchen.

Wir beschäftigen uns jedoch mit eigenen Algorithmen. Wir erstellen zum Schleifen und Schreibfunktionen jeden Tag; Wie können also gute Algorithmusentwurfsprinzipien das Schreiben dieser Funktionen beeinflussen?

Kennen Sie Ihre Eingabe

Eine der Hauptprinzipien des algorithmischen Designs besteht darin, den Algorithmus nach Möglichkeit so zu erstellen, dass die Eingabe selbst einen Teil der Arbeit für Sie erledigt. Wenn Sie beispielsweise wissen, dass Ihre Eingabe immer aus Zahlen besteht, müssen Sie keine Ausnahmen / Überprüfungen für Zeichenfolgen durchführen oder Ihre Werte in Zahlen zwingen. Wenn Sie wissen, dass Ihr DOM-Element jedes Mal in a identisch ist zum Schleife in JavaScript, sollten Sie nicht in jeder Iteration für dieses Element abfragen. Gleichzeitig in Ihrem zum Wenn Sie Schleifen verwenden, sollten Sie keine Komfortfunktionen mit Overhead verwenden, wenn Sie dasselbe mit (näheren) einfachen Operationen erreichen können.

// mach das nicht: for (var i = 1000; i> 0; i -) $ ("# foo"). append ("Bar"); // Stattdessen var foo = $ (" # foo "); var s =" "; for (var i = 1000; i> 0; i -) s + ="Bar"; foo.append (s);

Wenn Sie ein JavaScript-Entwickler sind (und Sie jQuery verwenden) und nicht wissen, was die oben genannten Funktionen tun und wie sie sich erheblich unterscheiden, ist der nächste Punkt für Sie.

Verstehen Sie Ihre Werkzeuge

Im besten Fall [Algorithmen] sind clevere, effiziente Methoden, um etwas zu tun, das ein höheres Maß an Intuition erfordert als die offensichtlichste Lösung.

Es ist leicht zu glauben, dass dies selbstverständlich ist. Es gibt jedoch einen Unterschied zwischen "wissen, wie man jQuery schreibt" und "Verständnis von jQuery". Wenn Sie Ihre Tools verstehen, bedeutet dies, dass Sie verstehen, was jede Codezeile bewirkt (sowohl sofort (Rückgabewert einer Funktion oder Auswirkung einer Methode) als auch implizit (wie viel Overhead ist die Ausführung einer Bibliotheksfunktion oder ist der effizienteste) Methode zum Verketten eines Strings). Um großartige Algorithmen zu schreiben, ist es wichtig, die Leistung von untergeordneten Funktionen oder Dienstprogrammen zu kennen, nicht nur deren Namen und Implementierung.

Die Umwelt verstehen

Das Entwerfen effizienter Algorithmen ist eine umfassende Aufgabe. Abgesehen davon, dass Sie Ihre Werkzeuge als eigenständige Komponente verstehen, müssen Sie auch die Art und Weise verstehen, in der sie mit dem größeren System interagieren. Um JavaScript in einer bestimmten Anwendung vollständig zu verstehen, ist es beispielsweise wichtig, das DOM und die Leistung von JavaScript in browserübergreifenden Szenarien zu verstehen, wie der verfügbare Speicher die Rendergeschwindigkeit beeinflusst, die Struktur der Server (und ihre Antworten), mit denen Sie interagieren können. sowie eine Vielzahl anderer Aspekte, die nicht greifbar sind, wie zum Beispiel Nutzungsszenarien.


Arbeitsaufwand reduzieren

Im Allgemeinen besteht das Ziel des Algorithmusentwurfs darin, einen Job in weniger Schritten auszuführen. (Es gibt einige Ausnahmen, z. B. Bcrypt-Hashing.) Berücksichtigen Sie beim Schreiben Ihres Codes alles der einfachen Operationen, die der Computer unternimmt, um das Ziel zu erreichen. Hier ist eine einfache Checkliste, um einen Weg zu einem effizienteren Algorithmusentwurf zu finden:

  • Sprachfunktionen verwenden, um Vorgänge zu reduzieren (variable Zwischenspeicherung, Verkettung usw.).
  • Reduzieren Sie die iterative Loop-Verschachtelung so weit wie möglich.
  • Definieren Sie, wenn möglich, Variablen außerhalb von Schleifen.
  • Verwenden Sie anstelle der manuellen Indexierung die automatische Loop-Indexierung (falls verfügbar).
  • Verwenden Sie clevere Reduktionstechniken wie rekursive Divide-, Eroberungs- und Abfrageoptimierung, um die Größe rekursiver Prozesse zu minimieren.

Lernen Sie fortgeschrittene Techniken

Es gibt keinen besseren Weg, ein besserer Algorithmus-Designer zu werden, als ein tiefes Verständnis und Verständnis für Algorithmen zu haben.

  • Nehmen Sie sich jede Woche ein bis zwei Stunden Zeit und lesen Sie die Kunst der Computerprogrammierung.
  • Versuchen Sie eine Facebook-Programmier-Challenge oder einen Google Codejam.
  • Lernen Sie, das gleiche Problem mit verschiedenen algorithmischen Techniken zu lösen.
  • Fordern Sie sich selbst heraus, indem Sie integrierte Funktionen einer Sprache implementieren, wie z .Sortieren(), mit Operationen auf niedrigerer Ebene.

Fazit

Wenn Sie nicht wussten, was ein Algorithmus zu Beginn dieses Artikels war, haben Sie hoffentlich jetzt ein konkreteres Verständnis für den etwas schwer fassbaren Begriff. Als professionelle Entwickler ist es wichtig, dass wir verstehen, dass der von uns geschriebene Code analysiert und optimiert werden kann, und es ist wichtig, dass wir uns die Zeit nehmen, diese Analyse der Leistung unseres Codes durchzuführen.

Hast du irgendwelche lustigen Algorithmusübungsprobleme gefunden? Vielleicht eine dynamische Programmierung "Rucksackproblem" oder "betrunkener Spaziergang"? Oder vielleicht kennen Sie einige bewährte Methoden der Rekursion in Ruby, die sich von den in Python implementierten Funktionen unterscheiden. Teilen Sie sie in den Kommentaren mit!