2009-11-07 25 views
8

Come ordinare in modo casuale circa 20 elementi con la complessità più bassa? (generazione di permutazioni casuali)Algoritmo per generare ordine casuale di elementi

+0

Cosa intendi con cca? –

+0

Analisi di correlazione canonica? –

+0

Cosa intendi con? : P –

risposta

21

Knuth's shuffle algorithm è una buona scelta.

+1

Deludente che qualcuno abbia detto qualcos'altro, francamente. –

+0

Beh, sono deluso che questa sia la risposta. Dal momento che devi prima ripetere l'elenco per riempirlo e poi rimescolarlo (con un algoritmo sicuramente buono), avrei pensato che c'era una soluzione migliore. – SourceOverflow

2

Alcuni mesi fa ho eseguito il blogging per ottenere una permutazione casuale di un elenco di numeri interi. Potresti usarlo come una permutazione degli indici del set che contiene i tuoi elementi, e poi hai quello che vuoi.

Nel primo post mi esplorare alcune possibilità, ed infine ottengo "una funzione per permutate caso un elenco generico con O (n) complessità" , correttamente incapsulato per lavorare su dati immutabili (cioè, è privo di effetti collaterali).

Nel secondo post, lo distribuisco in modo uniforme.

Il codice è in F #, spero che non ti dispiaccia!

Buona fortuna.

EDIT: Non ho una prova formale, ma l'intuizione mi dice che la complessità di un tale algoritmo non può essere inferiore a O (n). Mi piacerebbe davvero vederlo fatto più velocemente!

+0

la ricorsione nel secondo articolo è semplice .. penso che potrei usalo .. – Ante

+1

Tutte le permutazioni devono essere possibili, e riorganizzare un array in un disallineamento (cioè una permutazione 'p' per cui' p (k)! = k' per tutti i 'k') richiede che ogni elemento essere visitato Quindi O (n) caso peggiore. O è ancora abbastanza formale? –

+0

Anche O (n) caso medio della stessa dimostrazione, vieni a pensarci, dal momento che IIRC la proporzione di permutazioni di (1 ... n) che sono sconvolgimenti si avvicina a 1/e come n si avvicina all'infinito. –

1

Un modo semplice per rendere casuale l'ordine è creare un nuovo elenco delle dimensioni corrette (20 nel tuo caso), scorrere il primo elenco e aggiungere ciascun elemento in una posizione casuale al secondo elenco. Se la posizione casuale è già occupata, mettila nella successiva posizione libera.

penso che questo pseudocodice è corretto:

list newList 
foreach (element in firstList) 
    int position = Random.Int(0, firstList.Length - 1) 
    while (newList[position] != null) 
     position = (position + 1) % firstList.Length 
    newList[position] = element 

EDIT: Così si scopre che questa risposta non è in realtà che una buona. Non è né particolarmente veloce, né particolarmente casuale. Grazie per i vostri commenti. Per una buona risposta, si prega di scorrere indietro all'inizio della pagina :-)

+0

Nel caso peggiore questo algoritmo è O (n^2) (cioè, se il generatore di numeri casuali dice "1, 1, 1, 1, 1, 1, ...", ti lascio calcolare il resto) , non molto ottimizzato. –

+2

Mettere gli oggetti nella prossima posizione libera lo rende meno casuale. Gli oggetti manterranno il loro ordine originale più che in un casuale casuale shuffle. Per risolvere il problema dovresti scegliere una nuova posizione casuale quando viene presa una posizione, il che ovviamente lo rende molto più lento. – Guffa

+0

Questo è un buon punto, Guffa. Non l'avevo mai capito. Grazie. Almeno ho imparato qualcosa qui :-) –

1

Probabilmente qualcuno ha già implementato il mischiare per voi. Ad esempio, in Python è possibile utilizzare random.shuffle, in C++ random_shuffle e in PHP shuffle.

+0

hmm .. php forse? – Ante

+0

Sorprendentemente, in PHP si chiama 'shuffle' :) aggiorno la mia risposta. –

Problemi correlati