Sei sceso alla leggera, probabilmente non vuoi lavorare per un hedge fund in cui i quants non comprendono gli algoritmi di base :-)
Non v'è alcun modo per elaborare una struttura di dati arbitrariamente dimensioni in O(1)
se, come in questo caso, è necessario visitare ogni elemento almeno una volta. Il meglio che puoi sperare è O(n)
in questo caso, dov'è n
la lunghezza della stringa.
Sebbene, a parte, un O(n)
algoritmo nominale sarà essere O(1)
per una dimensione fissa ingresso così, tecnicamente, essi possono essere stati corretti qui. Tuttavia, di solito non è così che le persone usano l'analisi della complessità.
Mi sembra che potresti averli colpiti in molti modi.
Innanzitutto, informandoli che lo è non è possibile farlo, a O(1)
meno che non si usi il ragionamento "sospetto" di cui sopra.
In secondo luogo, mostrando le tue abilità d'élite fornendo codice Pythonic come:
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])
Questo produce:
[(123, 3), (234, 3), (345, 2)]
anche se, ovviamente, potresti modificare il formato di output in base a ciò che desideri.
E, infine, dicendo loro che non c'è quasi nessun problema con unO(n)
soluzione, poiché il codice sopra fornisce risultati per una stringa da un milione di cifre in meno di mezzo secondo. Sembra ridimensionare in modo abbastanza lineare, poiché una stringa di 10.000.000 di caratteri impiega 3,5 secondi e una di 100.000.000 di caratteri impiega 36 secondi.
E, se ne hanno bisogno meglio, ci sono modi per parallelizzare questo tipo di cose che possono accelerare notevolmente.
Ovviamente non all'interno di un singolo interprete Python, a causa di GIL, ma potresti dividere la stringa in qualcosa del genere ( vv
è necessaria la sovrapposizione indicata da per consentire una corretta elaborazione delle aree di confine):
vv
123412 vv
123451
5123456
Puoi coltivarli per separare i lavoratori e combinare i risultati in seguito.
La suddivisione dell'input e la combinazione dell'output rischiano di inondare qualsiasi salvataggio con stringhe di piccole dimensioni (e forse anche stringhe da un milione di cifre) ma, per set di dati molto più grandi, potrebbe fare la differenza. Il mio solito mantra di "misura, non indovinare" si applica qui, ovviamente.
Questo mantra si applica anche ad altre possibilità, come bypassare del tutto Python e usare un linguaggio diverso che potrebbe essere più veloce.
Ad esempio, il seguente codice C, in esecuzione sullo stesso hardware del precedente codice Python, gestisce un centinaio di milioni di cifre in 0,6 secondi, all'incirca la stessa quantità di tempo del codice Python elaborato un milione. In altre parole, molto più veloce:
#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;
}