Genera numeri casuali tranne alcuni valori

Voglio generare numeri casuali, ma non voglio che excludeRows dall’array excludeRows . Ecco il mio codice.

 public int generateRandom(int start, int end, ArrayList excludeRows) { Random rand = new Random(); int range = end - start +1 - excludeRows.size(); int random = rand.nextInt(range) + 1; for(int i = 0; i  random) { return random; } random++; } return random; } 

Uso questa funzione in un ciclo while e durante ogni iterazione aggiungo un nuovo valore a excludeRows . A volte restituisce numeri che appartengono a excludeRows . Qual è il problema?

 if(!exclude.contains(random)) return random; 

Prova questo ogni volta che restituirà il valore che non è in esclusione.

Penso che ci siano degli errori.

1) Il range dovrebbe essere end – start + 1, perché questo è il range desiderato.
2) Se vuoi davvero numeri casuali (come “casuali” nei computer), non dovresti solo ottenere il prossimo numero disponibile. Perché in questo caso il tuo numero casuale avrà le caratteristiche dei numeri esclusi densità / frequenza.

 public int generateRandom(int start, int end, ArrayList excludeRows) { Random rand = new Random(); int range = end - start + 1; int random; boolean success = false; while(!success) { random = rand.nextInt(range) + 1; for(Integer i: excludeRows) { if(i == random) { break; } else if (i > random) { success = true; break; } } } return random; } 

AGGIORNARE

Con la risposta di Achintya Jha il mio codice potrebbe essere migliorato (ma nota che ci sono anche alcune osservazioni):

 public int generateRandom(int start, int end, ArrayList excludeRows) { Random rand = new Random(); int range = end - start + 1; int random = rand.nextInt(range) + 1; while(excludeRows.contains(random)) { random = rand.nextInt(range) + 1; } return random; } 

Tu controlli:

 for(int i = 0; i < exclude.size(); i++) { if(exclude.get(i) > random) { return random; } 

e se solo il primo è più grande, restituirai il valore. Sei sicuro che l’ exclude è ordinata?

Puoi usare if(exclude.contains(random )) o il seguente algoritmo:

se (end-start) è un numero ragionevole, e hai bisogno di quasi tutti i valori puoi creare un elenco di tutti i numeri accettabili e usare random su questa dimensione dell’elenco e scegliere il valore casuale come indice. quindi rimuovere il numero indesiderato dall’elenco e ottenere un altro indice casuale.

In realtà, non abbiamo bisogno di usare contains(random) con un ciclo while.

Per semplificare la domanda, vediamo cosa succede se abbiamo un solo valore escluso. Possiamo dividere il risultato in 2 parti. Quindi il numero di valori possibili è range-1 . Se il numero casuale è inferiore al valore escluso, basta restituirlo. Altrimenti, potremmo aggiungere 1 .

Per multipli valori esclusi, possiamo suddividere il set di risultati in size+1 parti, dove per size intende il numero di valori esclusi. Quindi il numero di valori possibili è la range-size . Quindi ordiniamo i valori esclusi in ordine crescente. Se il numero casuale è inferiore al valore escluso meno i , allora restituiamo solo il numero casuale add i , dove i è l’indice del valore escluso.

 public int generateRandomNumberWithExcepts(int start, int end, List excepts) { int size = excepts.size(); int range = end - start + 1 - size; int randNum = random.nextInt(range) + start; excepts.sort(null); // sort excluding values in ascending order int i=0; for(int except : excepts) { if(randNum < except-i){ return randNum + i; } i++; } return randNum + i; }