Je veux créer un ensemble de nombres aléatoires sans doublons en Java.
Par exemple, j'ai un tableau pour stocker 10 000 entiers aléatoires de 0 à 9999.
Voici ce que j'ai jusqu'à présent:
import Java.util.Random;
public class Sort{
public static void main(String[] args){
int[] nums = new int[10000];
Random randomGenerator = new Random();
for (int i = 0; i < nums.length; ++i){
nums[i] = randomGenerator.nextInt(10000);
}
}
}
Mais le code ci-dessus crée des doublons. Comment puis-je m'assurer que les nombres aléatoires ne se répètent pas?
Integer[] arr = {...};
Collections.shuffle(Arrays.asList(arr));
Par exemple:
public static void main(String[] args) {
Integer[] arr = new Integer[1000];
for (int i = 0; i < arr.length; i++) {
arr[i] = i;
}
Collections.shuffle(Arrays.asList(arr));
System.out.println(Arrays.toString(arr));
}
Un algorithme simple qui vous donne des nombres aléatoires sans doublons se trouve dans le livre Programming Pearls p. 127.
Attention: le tableau résultant contient les nombres dans l'ordre! Si vous les voulez dans un ordre aléatoire, vous devez mélanger le tableau, avec Fisher – Yates shuffle ou en utilisant une liste et appelez Collections.shuffle()
.
L'avantage de cet algorithme est qu'il n'est pas nécessaire de créer un tableau avec tous les nombres possibles et que la complexité de l'exécution est toujours linéaire O(n)
.
public static int[] sampleRandomNumbersWithoutRepetition(int start, int end, int count) {
Random rng = new Random();
int[] result = new int[count];
int cur = 0;
int remaining = end - start;
for (int i = start; i < end && count > 0; i++) {
double probability = rng.nextDouble();
if (probability < ((double) count) / (double) remaining) {
count--;
result[cur++] = i;
}
remaining--;
}
return result;
}
Achintya Jha a la bonne idée ici. Au lieu de penser à la façon de supprimer les doublons, vous supprimez la possibilité de créer des doublons en premier lieu.
Si vous souhaitez vous en tenir à un tableau d’entités et si vous souhaitez randomiser leur ordre (manuellement, ce qui est assez simple), suivez ces étapes.
Votre code pourrait être modifié pour ressembler à ceci:
import Java.util.Random;
public class Sort
{
// use a constant rather than having the "magic number" 10000 scattered about
public static final int N = 10000;
public static void main(String[] args)
{
//array to store N random integers (0 - N-1)
int[] nums = new int[N];
// initialize each value at index i to the value i
for (int i = 0; i < nums.length; ++i)
{
nums[i] = i;
}
Random randomGenerator = new Random();
int randomIndex; // the randomly selected index each time through the loop
int randomValue; // the value at nums[randomIndex] each time through the loop
// randomize order of values
for(int i = 0; i < nums.length; ++i)
{
// select a random index
randomIndex = randomGenerator.nextInt(nums.length);
// swap values
randomValue = nums[randomIndex];
nums[randomIndex] = nums[i];
nums[i] = randomValue;
}
}
}
Et si j'étais vous, je diviserais probablement chacun de ces blocs en méthodes séparées et plus petites plutôt qu'en une seule méthode principale.
J'espère que cela t'aides.
Si vous avez besoin de générer des nombres avec des intervalles, cela peut être comme ça:
Integer[] arr = new Integer[((int) (Math.random() * (16 - 30) + 30))];
for (int i = 0; i < arr.length; i++) {
arr[i] = i;
}
Collections.shuffle(Arrays.asList(arr));
System.out.println(Arrays.toString(arr));`
Le résultat:
[1, 10, 2, 4, 9, 8, 7, 13, 18, 17, 5, 21, 12, 16, 23, 20, 6, 0, 22, 14, 24, 15, 3, 11, 19]
Remarque:
Si vous avez besoin que le zéro ne part pas, vous pouvez mettre un "si"
Que dis-tu de ça?
LinkedHashSet<Integer> test = new LinkedHashSet<Integer>();
Random random = new Random();
do{
test.add(random.nextInt(1000) + 1);
}while(test.size() != 1000);
L'utilisateur peut ensuite parcourir la Set
à l'aide d'une boucle for.
En Java 8, si vous voulez avoir un list
d'entiers aléatoires N
non répétitifs dans range (a, b)
, où b
est exclusif, vous pouvez utiliser quelque chose comme ceci:
Random random = new Random();
List<Integer> randomNumbers = random.ints(a, b).distinct().limit(N).boxed().collect(Collectors.toList());