Algoritmi dal libro.


358

Paul Erdos ha parlato del "Libro" in cui Dio conserva la prova più elegante di ogni teorema matematico. Ciò ha persino ispirato un libro (che credo sia giunto alla sua quarta edizione): Proofs from the Book .

Se Dio avesse un libro simile per gli algoritmi, quale algoritmo pensi che sarebbe un candidato?

Se possibile, fornisci anche un riferimento cliccabile e le informazioni chiave che lo fanno funzionare.

Solo un algoritmo per risposta, per favore.


11
Ottima domanda! [Modifica:} Una domanda. Dove tracciamo la linea tra algoritmi e strutture dati? Cosa succede se l'intuizione chiave di un algoritmo è intimamente correlata a una struttura di dati (ad esempio UNION FIND nella funzione inversa di Ackermann)?
Ross Snider,

4
una grande fonte e forse un candidato per un libro del genere è "Encyclopedia of Algorithms" springer.com/computer/theoretical+computer+science/book/…
Marcos Villagra

21
Sono un po 'sorpreso che gli algoritmi che considero piuttosto complicati (KMP, array di suffissi lineari) siano considerati da altri come "dal libro". Per me "dal libro" significa semplice ed evidente, ma solo con il senno di poi. Sono curioso di sapere come gli altri interpretano "elegante".
Radu GRIGore,

49
@supercooldave Non devi credere in Dio, ma dovresti credere nel suo libro. ;-)
Ross Snider

10
Durante una lezione del 1985, Erdős disse: "Non devi credere in Dio, ma dovresti credere nel Libro".
Robert Massaioli,

Risposte:


116

Union-find è un bel problema il cui miglior algoritmo / struttura di dati (Disjoint Set Forest ) si basa su uno stack di spaghetti. Sebbene sia abbastanza semplice e intuitivo da spiegare a un bambino intelligente, ci sono voluti diversi anni per avere un limite al suo tempo di esecuzione. Alla fine, si scoprì che il suo comportamento era correlato alla Funzione inversa di Ackermann, una funzione la cui scoperta segnò uno spostamento di prospettiva sul calcolo (e fu di fatto incluso in L'Infinito di Hilbert ).

Wikipedia offre una buona introduzione a Disjoint Set Forests .


109

Corrispondenza delle stringhe Knuth-Morris-Pratt . Le otto righe di codice più sottili che tu abbia mai visto.


4
È un po 'sbalorditivo rendersi conto che quello era qualcosa che non era ovvio in qualche momento ed è ovvio solo ora perché l'hanno inventato e l'abbiamo imparato ... Penso che dovremmo applicare la teoria della storia di Carr alla matematica e all'informatica .
Ritwik Bose,

1
Per la descrizione, direi che questo è legato alla ricerca di sottostringhe veloce di Boyer-Moore.
Bart il

2
@Mechko Il fatto che questo algoritmo sia stato scoperto simultaneamente e indipendentemente da persone separate indica che è ovvio in una certa misura. Se qualcosa è "ovvio" è una funzione dei vincoli del progetto e di un più ampio ambiente di programmazione. Se hai bisogno di (1) ricerca veloce del testo e (2) sei consapevole dell'importanza di algoritmi veramente O (n) e (3) hai già incontrato del testo con corrispondenze parziali prima e (4) hai il tempo per fare le cose "giuste", allora questo algoritmo è probabilmente ovvio.
Matt Gallagher,

In un'intervista Knuth ha affermato che l'idea dell'algoritmo è venuta dallo studio dell'automa finito bidirezionale di Stephen Cook per i palindromi.
Kaveh,

@Kaveh Si prega di leggere la Sezione 7 (Osservazioni storiche) dal documento KMP originale. Ha grandi osservazioni. A proposito di Morris che scrive un editor di testo che "era troppo complicato per essere compreso da altri implementatori del sistema". Informazioni su Knuth "la prima volta nell'esperienza di Knuth che la teoria degli automi gli aveva insegnato a risolvere un vero problema di programmazione meglio di quanto non potesse risolverlo prima". E "Knuth fu dispiaciuto di apprendere che Morris aveva già scoperto l'algoritmo, senza conoscere il teorema di Cook;". DIVERTIMENTO.
Hendrik Jan,

93

L'algoritmo di Blum, Floyd, Pratt, Rivest, e Tarjan per trovare il k -esimo elemento di una lista non ordinata nel tempo lineare è una bella algoritmo, e funziona solo perché i numeri sono appena a destra per adattarsi al Master Teorema. Va come segue:

  1. Ordina ogni sequenza di cinque elementi.
  2. Scegli la mediana in ciascuno.
  3. Ricorrere per trovare la mediana di questo elenco.
  4. Pivot sulla mediana delle mediane (come in Quicksort)
  5. Seleziona il lato corretto dell'elenco e la posizione in quell'elenco e ricorri.

3
Questo è uno dei miei algoritmi preferiti. Mi piace un'intuizione che ho appreso dal libro sulla discrepanza di Chazelle: l'insieme di mediane di gruppi di elementi è come una rete per gli intervalli nell'elenco ordinato dei numeri di input. Quindi l'algoritmo segue un paradigma generale: calcolare una -net veloce, risolvere il problema in rete, ricorrere a qualche parte dell'input per affinare la soluzione, fino ad avere la soluzione esatta. è una tecnica molto utileϵ ϵ1/ϵϵϵ
Sasho Nikolov,

5
A proposito, una volta parametrizzata la dimensione dei gruppi, le costanti non sono così magiche. sono ovviamente ottimizzati per dare la cosa giusta nel teorema del Maestro
Sasho Nikolov,

Implementazione di Ruby, gist.github.com/chadbrewbaker/7202412 Esiste una versione dell'algoritmo che utilizza lo spazio (costante, log) o è necessario utilizzare lo spazio scratch lineare per contenere le mediane?
Chad Brewbaker,

2
L'affermazione secondo cui "questo funziona solo perché i numeri sono giusti per adattarsi al teorema principale" non è proprio vera. Se si sostituisce il numero con un numero maggiore , è facile vedere che i due numeri che devono sommare a meno di convergono in e , quindi tutti sufficientemente grandi funzionano. è solo il primo numero che funziona, non è l'unico. n 1 3 / 4 0 n 55n13/40n5
Will Sawin,

88

Ricerca binaria è l'algoritmo più semplice, bello e utile che abbia mai incontrato.


Vorrei sostituire elegante con intuitivo. Non c'è niente di così elegante in questo; la sua semplicità è la sua vera bellezza.
Robert Massaioli,

@Robert Massaili: ho sostituito l'elegante con il bello. Avevi ragione su questo.
michalmocny,

2
E follemente difficile da scrivere correttamente - vedi " Sei uno del 10% dei programmatori che può scrivere una ricerca binaria? "
jon

Nel mio primo corso di algoritmi laureati abbiamo avuto quiz di 15 minuti in cui dovevamo risolvere manualmente 2-3 problemi. Il primo di questi quiz includeva un albero di ricerca binario e due domande sugli heap. Ero imbarazzato e sgomento di sapere che avevo sbagliato il problema di ricerca binaria, prima di sentirmi dire che in una classe di circa 30 persone c'erano due risposte corrette. Ma anche sapendolo, il fatto che la comunità professionale abbia impiegato 15 anni per fare le cose giuste è sbalorditivo.
Stella Biderman,

84

Sono sorpreso di non vedere l' algoritmo di Floyd-Warshall per i percorsi più brevi di tutte le coppie qui:

d[]: 2D array. d[i,j] is the cost of edge ij, or inf if there is no such edge.

for k from 1 to n:
  for i from 1 to n:
    for j from 1 to n:
      d[i,j] = min(d[i,j], d[i,k] + d[k,j])

Uno degli algoritmi non banali più brevi e chiari in corso, e le prestazioni di sono molto veloci se si considera che potrebbero esserci dei bordi . Sarebbe il mio bambino poster per la programmazione dinamica!O ( n 2 )O(n3)O(n2)


2
Questo algoritmo può anche essere generalizzato in un modo davvero accurato. Vedi ad es. R6.ca/blog/20110808T035622Z.html e cl.cam.ac.uk/~sd601/papers/semirings.pdf
Mikhail Glushenkov


73

Potrebbe sembrare un po 'banale (soprattutto rispetto alle altre risposte), ma penso che Quicksort sia davvero elegante. Ricordo che quando l'ho visto per la prima volta ho pensato che fosse davvero complicato, ma ora sembra fin troppo semplice.


10
Quicksort solleva anche interessanti domande su quale sia esattamente l'essenza di un algoritmo. Ad esempio, l'implementazione standard di Haskell appare esattamente come la definizione standard di pseudo-codice, ma presenta una complessità asintotica diversa. Quindi, Quicksort è solo una questione di divisione e conquista o l'intelligente puntatore in-situ del violinista è una parte essenziale di Quicksort? Quicksort può anche essere implementato in un ambiente puramente funzionale o richiede mutabilità?
Jörg W Mittag,

2
L'idea dell '"essenza" o della "morale" di un algoritmo proviene ovviamente dal bellissimo documento The Genuine Sieve of Eratosthenes di Melissa E. O'Neill ( cs.hmc.edu/~oneill/papers/Sieve-JFP. pdf ) e la discussione quicksort proviene dalla discussione LtU di quel documento ( lambda-the-ultimate.org/node/3127 ), partendo in particolare da questo commento: lambda-the-ultimate.org/node/3127/#comment-45549
Jörg W Mittag,

8
@Jörg: l'implementazione di quicksort su elenchi collegati è completamente sensata e ha lo stesso tempo di esecuzione asintotico della sua implementazione sul posto sugli array (diamine, anche l'implementazione fuori posto ingenua sugli array ha lo stesso tempo di esecuzione) - entrambi su nella media e nel peggiore dei casi. Per quanto riguarda l'utilizzo dello spazio, questo è davvero diverso, ma va detto che anche la versione "sul posto" richiede uno spazio extra non costante (stack di chiamate!), Un fatto facilmente trascurato.
Konrad Rudolph,

Vale anche la pena menzionare Quicksort Dual-Pivot di Vladimir Yaroslavskiy. Questo dovrebbe essere almeno il 20% più veloce originale quicksort permalink.gmane.org/gmane.comp.java.openjdk.core-libs.devel/…
SaveTheRbtz

Quicksort in teoria è semplice (può essere delineato in 4 passaggi) e potrebbe essere altamente ottimizzato, ma in pratica è molto difficile codificare correttamente. Ecco perché non ottiene il mio voto.
Dennis,


50

Il test di primalità di Miller-Rabin (e test simili) dovrebbe essere in The Book. L'idea è quella di sfruttare le proprietà dei numeri primi (cioè usando il piccolo teorema di Fermat) per cercare probabilisticamente una testimonianza del numero non primo. Se nessun testimone viene trovato dopo un numero sufficiente di test casuali, il numero viene classificato come primo.

In quella nota, il test di primalità di AKS che ha mostrato che PRIMES è in P dovrebbe certamente essere nel Libro!


49

Test di identità polinomiale con il lemma di Schwartz-Zippel :

Se qualcuno ti svegliasse nel cuore della notte e ti chiedesse di testare due espressioni polinomiali univariate per l'identità, probabilmente le riduresti alla forma normale della somma dei prodotti e le confronteresti per l'identità strutturale. Sfortunatamente, la riduzione può richiedere tempo esponenziale; è analogo alla riduzione delle espressioni booleane in forma disgiuntiva normale.

Supponendo che tu sia il tipo a cui piacciono gli algoritmi randomizzati, il tuo prossimo tentativo sarebbe probabilmente quello di valutare i polinomi in punti scelti casualmente in cerca di controesempi, dichiarando i polinomi molto probabilmente identici se superano abbastanza test. Il lemma di Schwartz-Zippel mostra che con l'aumentare del numero di punti, la probabilità di un falso positivo diminuisce molto rapidamente.

Non è noto alcun algoritmo deterministico per il problema che viene eseguito nel tempo polinomiale.


Questo avrebbe dovuto essere suggerito molto tempo fa! Grazie!
Arnab,

1
Ci sono molti altri algoritmi randomizzati che meritano un posto di rilievo nel Libro. Per questi il ​​contrasto tra le alternative deterministiche e probabilistiche è meno evidente: un algoritmo deterministico di solito esiste ma è molto più complicato.
Per Vognsen,

Ho inventato indipendentemente lo stesso algoritmo mentre stavo lavorando su un documento un paio di anni fa fino a quando qualcuno mi ha chiesto non è il lemma di Schwartz-Zippel? E ho detto, che cos'è? :)
Elio

46

Profondità Prima ricerca . È la base di molti altri algoritmi. È anche ingannevolmente semplice: ad esempio, se si sostituisce la coda in un'implementazione BFS con uno stack, si ottiene DFS?


1
È anche la base dell'esecuzione di Prolog!
muad,

1
Qual è il punto su BFS con uno stack che mi manca? Avrei pensato che la risposta fosse "sì, ottieni DFS".
Omar Antolín-Camarena,

1
Bene, tutti sembrano pensare che questo problema sia banale. Inoltre, tutti sembrano pensare che la risposta sia "sì", il che è sbagliato. La risposta è in realtà "dipende da quale implementazione BFS inizi". Vedi cs.stackexchange.com/questions/329/… (Questa è una domanda che ho pubblicato per aiutare con la fase beta di CS.SE)
Radu GRIGore,

Viene anche brevemente discusso qui: ics.uci.edu//~eppstein/161/960215.html
Radu GRIGore,

42

L'algoritmo di Dijkstra : il problema del percorso più breve a sorgente singola per un grafico con costi del percorso del bordo non negativi. È usato ovunque ed è uno degli algoritmi più belli là fuori. Internet non può essere instradato senza di essa - è una parte fondamentale dei protocolli di routing IS-IS e OSPF (Open Shortest Path First).

  1. Assegna a ciascun nodo un valore di distanza. Impostalo su zero per il nostro nodo iniziale e su infinito per tutti gli altri nodi.
  2. Contrassegna tutti i nodi come non visitati. Imposta il nodo iniziale come corrente.
  3. Per il nodo corrente, considera tutti i suoi vicini non visitati e calcola la loro distanza provvisoria (dal nodo iniziale). Ad esempio, se il nodo corrente (A) ha una distanza di 6 e un bordo che lo collega a un altro nodo (B) è 2, la distanza da B a A sarà 6 + 2 = 8. Se questa distanza è inferiore alla distanza precedentemente registrata (infinito all'inizio, zero per il nodo iniziale), sovrascrivere la distanza.
  4. Quando abbiamo finito di considerare tutti i vicini del nodo corrente, contrassegnalo come visitato. Un nodo visitato non verrà mai più verificato; la sua distanza registrata ora è definitiva e minima.
  5. Se tutti i nodi sono stati visitati, finire. In caso contrario, impostare il nodo non visitato con la distanza minima (dal nodo iniziale) come il "nodo corrente" successivo e continuare dal passaggio 3.


40

Lo schema di crittografia completamente omomorfo di Gentry (sia su reticoli ideali che su numeri interi) è terribilmente bello. Consente a terzi di eseguire calcoli arbitrari su dati crittografati senza accesso a una chiave privata.

Lo schema di crittografia è dovuto a diverse osservazioni acute.

  • Per ottenere uno schema di crittografia completamente omomorfo, è sufficiente disporre di uno schema omomorfo rispetto all'addizione e alla moltiplicazione. Questo perché l'addizione e la moltiplicazione (mod 2) sono sufficienti per ottenere porte AND, OR e NOT (e quindi Turing Completeeness).
  • Che se si dovesse avere un tale schema, ma a causa di alcune limitazioni potrebbe essere eseguito solo per circuiti di una certa profondità finita, allora si può valutare omomorficamente la procedura di decrittazione e re-crittografia per ripristinare la limitazione della profondità del circuito senza sacrificare la privacy delle chiavi.
  • Che "schiacciando" la profondità della versione del circuito della funzione di decrittazione per lo schema, si potrebbe consentire a uno schema originariamente limitato a circuiti finiti e superficiali un numero arbitrario di calcoli.

Nella sua tesi, Craig Gentry ha risolto un problema aperto (e meraviglioso) di lunga data nella crittografia. Il fatto che esista uno schema completamente omomorfo esige che riconosciamo che esiste una struttura intrinseca alla calcolabilità che altrimenti potremmo aver ignorato.

http://crypto.stanford.edu/craig/craig-thesis.pdf

http://eprint.iacr.org/2009/616.pdf

http://portal.acm.org/citation.cfm?id=1666420.1666445



38

Algoritmo di Strassen per la moltiplicazione di matrici.


Probabilmente aspetterebbe fino a quando non sapremo se è ottimale.
Thomas Ahle,

Non è ottimale, almeno asintoticamente ... Penso che includere l'algoritmo di Strassen ti costringa a includere prima l'algoritmo di Karatsuba.
Timothy Sun,


34

L'algoritmo del tempo lineare per la costruzione di array di suffissi è veramente bello, sebbene non abbia ricevuto il riconoscimento che meritava http://www.cs.helsinki.fi/u/tpkarkka/publications/icalp03.pdf


Io non penso che abbia ottenuto il riconoscimento che merita - cosa ti fa pensare altrimenti? Ad esempio, è implementato nella libreria di analisi delle sequenze C ++ SeqAn.
Konrad Rudolph,

Vale la pena ricordare che ora ci sono un certo numero di altri algoritmi di costruzione di array di suffissi temporali lineari e non lineari che, sebbene non altrettanto belli, potrebbero essere molto più veloci nella pratica. "Un approccio efficiente e versatile all'ordinamento dei suffissi", Journal of Experimental Algorithmics (JEA), Volume 12, giugno 2008 ha ottenuto alcuni risultati sperimentali in tal senso.
Raffaello,

@Raphael: sono un po 'diffidente nei confronti del fatto che a p. 3 di quel documento JEA, danno solo ciò che "credono" sia un limite "sciolto" di O (n ^ 2 log n) ... Conosci qualche documento con algoritmi a tempo lineare dimostrabilmente più veloci nella pratica rispetto al Algoritmo distorto?
user651

32

Eliminazione gaussiana. Completa la sequenza di generalizzazione dall'algoritmo GCD euclideo a Knuth-Bendix.


A proposito, qual è la sequenza di generalizzazione e dove si inserisce l'algoritmo di Buchberger per Grobner? (Sembra analogo a Knuth-Bendix, ma ho visto da qualche parte menzionare che generalizza l'eliminazione gaussiana ...)
ShreevatsaR

6
la sequenza è: GCD euclideo -> Eliminazione gaussiana -> Buchberger -> Knuth-Bendix. Si può anche inserire (al posto dell'eliminazione gaussiana) la divisione e il modulo polinomiali univariati (nell'ordine di generalizzazione è "a parte" dall'eliminazione gaussiana, GE è il grado 1 multivariato, l'anello polinomiale è grado illimitato univariato, il grado di Buchberger è grado illimitato multivariato. il salto di generalizzazione è più grande da EGCD ​​a GE o anello polinomiale a causa dell'aggiunta di variabili, e quindi anche da Buchberger a KB a causa della firma illimitata.
Mitch

+1: l'algoritmo euclideo risolve l'equazione più celebre ax-by = 1 in matematica. Perché non si presenta più spesso in CS è un mistero.
Tegiri Nenashi,

32

Sono rimasto impressionato quando ho visto l'algoritmo per la prima volta il campionamento del serbatoio e la sua prova. È il tipico puzzle di tipo "rompicapo" con una soluzione estremamente semplice. Penso che appartenga sicuramente al libro, sia per gli algoritmi che per i teoremi matematici.

Per quanto riguarda il libro, la storia narra che quando Erdös morì e andò in paradiso, chiese di incontrarsi con Dio. La richiesta fu accolta e per l'incontro Erdös ebbe una sola domanda. "Posso guardare nel libro?" Dio disse di sì e condusse Erdös ad esso. Naturalmente molto emozionato, Erdös apre il libro solo per vedere quanto segue.

Teorema 1: ...
Prova: ovvio.

Teorema 2: ...
Prova: ovvio.

Teorema 3: ...
Prova: ovvio.


4
Teorema 4: ... Prova: esercizio per il lettore.
Jon

31

La tartaruga e la lepre algoritmo . Mi piace perché sono sicuro che anche se avessi sprecato tutta la mia vita cercando di trovarlo, non avrei mai avuto un'idea del genere.


6
Conosci l'algoritmo stupido che risolve il problema con la stessa asintotica e segue un modello di progettazione algoritmica? Sto parlando di approfondimento iterativo. Nell'ennesima iterazione si inizia dal 2 ^ ennesimo successore della radice e si guardano in avanti 2 ^ n successori alla ricerca di una ricorrenza. Anche se stai ripercorrendo alcuni dei tuoi passaggi con ogni iterazione, il tasso di crescita geometrica del raggio di ricerca significa che non influisce sugli asintotici.
Per Vognsen,

30

Un esempio fondamentale e "banale" come la prova di Euclide di infiniti numeri primi:

2-approssimazione per MAX-CUT - Indipendentemente per ciascun vertice, assegnarlo a una delle due partizioni con uguale probabilità.


6
Sì, un algoritmo molto carino. Meno banalmente, al costo di un altro fattore 2, questo algoritmo funziona anche per massimizzare qualsiasi funzione sottomodulare, non solo la funzione di taglio del grafico. Questo è il risultato di Feige, Mirrokni e Vondrak del FOCS 07
Aaron Roth,

30

Sono sempre stato parziale all'algoritmo di Christofides che fornisce una approssimazione (3/2) per il TSP metrico. In effetti, chiamami facile da accontentare, ma mi è persino piaciuto l'algoritmo di approssimazione 2 che lo precede . Il trucco di Christofides di realizzare un Eulerian con albero a peso minimo aggiungendo una corrispondenza dei suoi vertici di grado dispari (invece di duplicare tutti i bordi) è semplice ed elegante, e basta poco per convincerne uno che questa corrispondenza non ha più della metà del peso di un tour ottimale.


In effetti, ci sono anche molti altri algoritmi di approssimazione semplici ed eleganti con garanzie di approssimazione decenti.
Janne H. Korhonen,



25

Algoritmi per la programmazione lineare : metodi di punto simplex, ellissoide e punto interno.

http://en.wikipedia.org/wiki/Linear_programming#Algorithms


E in effetti, diversi premi Nobel sono stati assegnati per far progredire la nostra comprensione di questi problemi.
Ross Snider,

@Ross Kantorovich ha vinto il premio Nobel per l'economia per aver inventato LP e averlo applicato alle risorse assegnate. A quali altri premi stavi pensando?
Mark Reitblatt,

@Mark Koopermans ha ricevuto il premio nobel con Kantorovich, ma era ancora inesatto da parte mia dire "diversi".
Ross Snider,

22

Algoritmo di Robin Moser per la risoluzione di una determinata classe di istanze SAT. Tali casi sono risolvibili da Lovasz Local Lemma. L'algoritmo Moser è in effetti una de-randomizzazione dell'affermazione del lemma.

Penso che tra qualche anno il suo algoritmo (e la tecnica per la sua prova di correttezza) sarà ben digerito e perfezionato al punto da essere un candidato valido per un algoritmo dal Libro .

Questa versione è un'estensione del suo documento originale, scritto con Gábor Tardos.


21

L'algoritmo più veloce e breve di Marcus Hutter per tutti i problemi ben definiti .

Questo tipo di va contro lo spirito delle altre offerte in questo elenco, dal momento che è solo di interesse teorico e non pratico, ma poi di nuovo il tipo di titolo dice tutto. Forse dovrebbe essere incluso come un ammonimento per coloro che guarderebbero solo al comportamento asintotico di un algoritmo.


21

L'algoritmo X di Knuth trova tutte le soluzioni all'esatto problema di copertura . Ciò che è così magico al riguardo è la tecnica che ha proposto di implementarlo in modo efficiente: Dancing Links .


20

Penso che dobbiamo includere quello di Schieber-Vishkin , che risponde alle domande più basse degli antenati comuni in tempo costante, preelaborando la foresta in tempo lineare.

Mi piace l'esposizione di Knuth nel Volume 4 Fascicle 1 e il suo pensiero . Ha detto che gli ci sono voluti due interi giorni per capirlo appieno, e ricordo le sue parole:

Penso che sia abbastanza bello, ma sorprendentemente ha una cattiva stampa in letteratura (..) È basato sulla matematica che mi entusiasma.


10
Aspetta, potrebbe essere bello, ma se Knuth ha impiegato due giorni interi per capirlo appieno, è davvero "dal libro"?
ShreevatsaR,

@ShreevatsaR Il libro ha una stampa fine nelle note a piè di pagina :)
hsmyers,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.