Javaで重複することなく一連の乱数を作成したい。
たとえば、0〜9999の10,000個のランダムな整数を格納する配列があります。
ここに私がこれまで持っているものがあります:
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);
}
}
}
しかし、上記のコードは複製を作成します。乱数が繰り返されないようにするにはどうすればよいですか?
Integer[] arr = {...};
Collections.shuffle(Arrays.asList(arr));
例えば:
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));
}
重複することなく乱数を提供する簡単なアルゴリズムは、本で見つけることができます Programming Pearls p。 127。
注意:結果の配列には順番に数字が含まれています!ランダムな順序にしたい場合は、 Fisher–Yates shuffle を使用するか、Listを使用してCollections.shuffle()
を呼び出して、配列をシャッフルする必要があります。
このアルゴリズムの利点は、すべての可能な数の配列を作成する必要がなく、実行時の複雑さが線形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はここで正しい考えを持っています。重複を削除する方法を考える代わりに、最初に重複を作成する機能を削除します。
Intの配列に固執し、それらの順序をランダム化する(手動で、これは非常に簡単です)場合は、次の手順を実行します。
コードは次のように変更できます。
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;
}
}
}
そして、私があなただったら、これらのブロックのそれぞれを、1つの大きなメインメソッドを持つのではなく、別々の小さなメソッドに分割するでしょう。
お役に立てれば。
間隔付きの数値を生成する必要がある場合は、次のようにすることができます。
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));`
結果:
[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]
注意:
ゼロが残らないようにする必要がある場合は、「if」を置くことができます
これはどう?
LinkedHashSet<Integer> test = new LinkedHashSet<Integer>();
Random random = new Random();
do{
test.add(random.nextInt(1000) + 1);
}while(test.size() != 1000);
その後、ユーザーはforループを使用してSet
を反復処理できます。
In Java 8、range (a, b)
の非反復list
ランダム整数のN
が必要な場合、b
は排他的です。次のようなものを使用できます。
Random random = new Random();
List<Integer> randomNumbers = random.ints(a, b).distinct().limit(N).boxed().collect(Collectors.toList());