2015-09-06 4 views
5

Ho questo metodo che genera un numero (1-10) per ciascun valore di matrice elencato in questo metodo. Voglio che l'intero set di numeri sia visualizzato come un insieme di numeri univoci. Come fare questo?Genera un numero casuale univoco per ciascun valore di matrice

public static int generateNumbers(int[] lotteryNumbers) { 

    Random randNum = new Random(); 

    lotteryNumbers[0] = randNum.nextInt(10); 
    lotteryNumbers[1] = randNum.nextInt(10); 
    lotteryNumbers[2] = randNum.nextInt(10); 
    lotteryNumbers[3] = randNum.nextInt(10); 
    lotteryNumbers[4] = randNum.nextInt(10); 

    return lotteryNumbers[4]; 
} 
+0

Non si dovrebbe usare casuale. –

+2

Duplicato di http: // StackOverflow.it/questions/8115722/generation-unique-random-numbers-in-java – Satya

+1

@nikpon cosa c'è di sbagliato in 'Random'? È perfettamente soddisfacente – Dici

risposta

5

Una soluzione semplice è quella di generare un elenco di 10 cifre, rimescola quella lista e ottenere i primi cinque elementi:

List<Integer> list = new ArrayList<>(10); 
for (int i = 0; i < 10; i++) { 
    list.add(i); 
} 
Collections.shuffle(list); 
Integer[] lotteryNumbers = list.subList(0, 5).toArray(new Integer[10]); 

Collections.shuffle(list) è un metodo di utilità che permuta casualmente nell'elenco di cui posto .

Se si utilizza Java 8, questo può essere scritta come:

List<Integer> list = IntStream.range(0, 10).boxed().collect(Collectors.toList()); 
Collections.shuffle(list); 
int[] loterryNumbers = list.subList(0, 5).stream().mapToInt(i -> i).toArray(); 
+0

Grazie a @Tunkai. Ma c'è un modo in cui posso generare numeri univoci usando Random? perché mi è permesso usare solo a caso dato che è un compito scolastico. –

+1

Non esiste un modo integrato. Quello che puoi fare è generare un int usando Random in un ciclo finché il numero che hai ottenuto non è stato trovato prima. – Tunaki

+0

@ N. Vedi la mia risposta, è fondamentalmente lo stesso algoritmo di 'Collections.shuffle' ma senza usare un metodo di libreria. È bello sapere ed è anche utile per il tuo compito, ma tieni presente che nella vita reale la risposta di Tunaki è migliore. Non mi dispiacerebbe se avessi svalutato il mio però: D – Dici

3

Una tecnica ingenuo è quello di scegliere in modo casuale nel set che si desidera "shuffle":

public static int[] generateNumbers(int exclusiveMaxValue) { 
    List<Integer> values = new ArrayList<>(exclusiveMaxValue); 
    for (int i=0 ; i<values.size() ; i++) values.add(i); 

    int[] result = new int[exclusiveMaxValue]; 
    Random rd = new Random(); 
    for (int i=0 ; i<result.length ; i++) { 
     result[i] = values.remove(rd.nextInt(values.size())); 
    } 
    return result; 
} 

Tuttavia, List.remove è in genere O(n), quindi l'intero metodo è quadratico, che è molto costoso. È possibile eseguire un riordino in O(n) da elementi semplicemente sostituendo al posto (che è quello che fa Collections.shuffle):

public static int[] generateNumbers(int exclusiveMaxValue) { 
    int[] result = new int[exclusiveMaxValue]; 
    for (int i=0 ; i<result.length ; i++) result[i] = i; 

    Random rd = new Random(); 
    for (int i=result.length - 1 ; i>=0 ; i--) { 
     swap(result, i, rd.nextInt(i + 1)); 
    } 
    return result; 
} 

private static swap(int[] arr, int i, int j) { 
    int tmp = arr[i]; 
    arr[i] = arr[j]; 
    arr[j] = tmp; 
} 
1

Questo metodo genera la sequenza di lunghezza N di numeri unici nell'intervallo [0, N -1].

public static int[] generateNumbers(int length) { 
    final int[] array = new int[length]; 
    for (int i = 0; i < length; ++i) { 
     array[i] = i; 
    } 
    shuffle(array); 
    return array; 
} 

per mischiare algoritmo di Fisher-Yates è stato utilizzato:

public static void shuffle(final int[] array) { 
    final Random random = new Random(); 
    for (int i = array.length - 1; i > 0; --i) { 
     final int randomIdx = random.nextInt(i + 1); 
     final int temp = array[i]; 
     array[i] = array[randomIdx]; 
     array[randomIdx] = temp; 
    } 
} 
  • Grazie di (Ronald Fisher and Frank Yates) tempo la complessità dell'algoritmo è O (n)
  • Questa implementazione funziona su array (con primitive) non sulle raccolte (con istanze della classe Integer che racchiude un valore del tipo primitivo int in un oggetto) - è importante se la dimensione dell'array è sufficientemente grande
0

Ecco un modo alternativo che utilizza un set e lo riempie fino a raggiungere le dimensioni richieste. Genera numeri ToDraw numeri casuali distinti nell'intervallo da min a max (incluso). Conserva anche l'ordine in cui sono stati estratti i numeri (questo è ciò che è LinkedHashSet).

private static Set<Integer> drawNumbers(int min, int max, int numbersToDraw) { 
    if (max < min) { 
     throw new IllegalArgumentException("Minimum must be less than maximum."); 
    } 
    if (max < 0 || min < 0) { 
     throw new IllegalArgumentException("Both range numbers must be positive."); 
    } 
    final int countOfNumbers = max - min + 1; 
    if (countOfNumbers < numbersToDraw) { 
     throw new IllegalArgumentException("Range is not big enough."); 
    } 
    final Random randomizer = new SecureRandom(); 
    final Set<Integer> numbersDrawn = new LinkedHashSet<>(); 
    while (numbersDrawn.size() < numbersToDraw) { 
     final int randomNumber = min + randomizer.nextInt(countOfNumbers); 
     numbersDrawn.add(randomNumber); 
    } 
    return numbersDrawn; 
} 

Se non si richiedono i numeri per essere unico, è possibile utilizzare questo in Java 8:

final Random randomizer = new SecureRandom(); 

final List<Integer> numbersDrawn = IntStream 
     .range(0, numbersToDraw) 
     .mapToObj(i -> min + randomizer.nextInt(max - min + 1)) 
     .collect(Collectors.toList()); 

Se non si richiedono i numeri per essere unico, ma si desidera stampare i loro valori distinti (è che la tua domanda originale?):

final Random randomizer = new SecureRandom(); 

final Set<Integer> numbersDrawn = IntStream 
     .range(0, numbersToDraw) 
     .mapToObj(i -> min + randomizer.nextInt(max - min + 1)) 
     .collect(Collectors.toSet()); 

E un'altra alternativa per il vostro caso concreto:

final Set<Integer> distinctNumbers = Arrays 
    .stream(lotteryNumbers) 
    .distinct() // you can leave this as the set is distinct automatically 
    .boxed() 
    .collect(Collectors.toSet());