Sie sind leichtfertig ausgestiegen und möchten wahrscheinlich nicht für einen Hedgefonds arbeiten, bei dem die Quants grundlegende Algorithmen nicht verstehen :-)
Es gibt keine Möglichkeit, eine Datenstruktur beliebiger Größe zu verarbeiten, O(1)
wenn Sie wie in diesem Fall jedes Element mindestens einmal besuchen müssen. Das Beste, auf das Sie hoffen können, ist O(n)
in diesem Fall, wo n
die Länge der Zeichenfolge ist.
Obwohl, wie nebenbei bemerkt, ein nominaler O(n)
Algorithmus wird sein O(1)
für eine feste Eingangsgröße so, technisch gesehen , kann sie richtig hier gewesen. Normalerweise verwenden Menschen die Komplexitätsanalyse jedoch nicht so.
Mir scheint, Sie hätten sie auf verschiedene Weise beeindrucken können.
Indem Sie sie zunächst darüber informieren, dass dies nicht möglich ist, es O(1)
sei denn, Sie verwenden die oben angegebene "verdächtige" Argumentation.
Zweitens, indem Sie Ihre Elite-Fähigkeiten unter Beweis stellen, indem Sie Pythonic-Code wie den folgenden bereitstellen:
inpStr = '123412345123456'
# O(1) array creation.
freq = [0] * 1000
# O(n) string processing.
for val in [int(inpStr[pos:pos+3]) for pos in range(len(inpStr) - 2)]:
freq[val] += 1
# O(1) output of relevant array values.
print ([(num, freq[num]) for num in range(1000) if freq[num] > 1])
Dies gibt aus:
[(123, 3), (234, 3), (345, 2)]
Natürlich können Sie das Ausgabeformat nach Belieben ändern.
Und schließlich, wenn man ihnen sagt, dass es mit ziemlicher Sicherheit keine gibt Problem mit einer O(n)
Lösung, da der obige Code in weniger als einer halben Sekunde Ergebnisse für eine einstellige Zeichenfolge liefert. Es scheint auch ziemlich linear zu skalieren, da eine Zeichenfolge mit 10.000.000 Zeichen 3,5 Sekunden und eine Zeichenfolge mit 100.000.000 Zeichen 36 Sekunden dauert.
Und wenn sie Besseres brauchen , gibt es Möglichkeiten, solche Dinge zu parallelisieren, die es erheblich beschleunigen können.
Natürlich nicht innerhalb eines einzelnen Python-Interpreters, aufgrund der GIL, aber Sie könnten die Zeichenfolge in so etwas aufteilen (eine Überlappung vv
ist erforderlich, um eine ordnungsgemäße Verarbeitung der Grenzbereiche zu ermöglichen):
vv
123412 vv
123451
5123456
Sie können diese auf separate Mitarbeiter verteilen und die Ergebnisse anschließend kombinieren.
Die Aufteilung der Eingabe und die Kombination der Ausgabe überschwemmen wahrscheinlich jede Einsparung mit kleinen Zeichenfolgen (und möglicherweise sogar Zeichenfolgen mit Millionen Ziffern), aber bei viel größeren Datenmengen kann dies durchaus einen Unterschied bewirken. Hier gilt natürlich mein übliches Mantra "Messen, nicht raten" .
Dieses Mantra gilt auch für andere Möglichkeiten, z. B. die Umgehung von Python insgesamt und die Verwendung einer anderen Sprache, die möglicherweise schneller ist.
Der folgende C-Code, der auf derselben Hardware wie der frühere Python-Code ausgeführt wird, verarbeitet beispielsweise hundert Millionen Ziffern in 0,6 Sekunden, ungefähr so lange, wie der Python-Code eine Million verarbeitet hat . Mit anderen Worten, viel schneller:
#include <stdio.h>
#include <string.h>
int main(void) {
static char inpStr[100000000+1];
static int freq[1000];
// Set up test data.
memset(inpStr, '1', sizeof(inpStr));
inpStr[sizeof(inpStr)-1] = '\0';
// Need at least three digits to do anything useful.
if (strlen(inpStr) <= 2) return 0;
// Get initial feed from first two digits, process others.
int val = (inpStr[0] - '0') * 10 + inpStr[1] - '0';
char *inpPtr = &(inpStr[2]);
while (*inpPtr != '\0') {
// Remove hundreds, add next digit as units, adjust table.
val = (val % 100) * 10 + *inpPtr++ - '0';
freq[val]++;
}
// Output (relevant part of) table.
for (int i = 0; i < 1000; ++i)
if (freq[i] > 1)
printf("%3d -> %d\n", i, freq[i]);
return 0;
}