web-dev-qa-db-ja.com

Java非反復乱数の生成

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);
        }
    }
}

しかし、上記のコードは複製を作成します。乱数が繰り返されないようにするにはどうすればよいですか?

30
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));

}
41
Achintya Jha

重複することなく乱数を提供する簡単なアルゴリズムは、本で見つけることができます 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;
}
7
the

Achintya Jhaはここで正しい考えを持っています。重複を削除する方法を考える代わりに、最初に重複を作成する機能を削除します。

Intの配列に固執し、それらの順序をランダム化する(手動で、これは非常に簡単です)場合は、次の手順を実行します。

  1. サイズnの配列を作成します。
  2. ループし、インデックスiの各値を値iに初期化します(または、0〜n-1ではなく1〜nの数字を使用する場合はi + 1)。
  3. 最後に、配列をループして、各値をランダムインデックスの値に再度交換します。

コードは次のように変更できます。

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つの大きなメインメソッドを持つのではなく、別々の小さなメソッドに分割するでしょう。

お役に立てれば。

3

間隔付きの数値を生成する必要がある場合は、次のようにすることができます。

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」を置くことができます

2
Marcus person

これはどう?

LinkedHashSet<Integer> test = new LinkedHashSet<Integer>();
Random random = new Random();
do{
    test.add(random.nextInt(1000) + 1);
}while(test.size() != 1000);

その後、ユーザーはforループを使用してSetを反復処理できます。

0
Jitin Kodian

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());
0