2015-09-06 9 views
5

このメソッドでは、このメソッドにリストされている各配列の値の数(1-10)を生成します。私は数字のセット全体を一意の数字のセットとして表示したい。これを行う方法?各配列の値に一意の乱数を生成します

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

ランダムは使用しないでください。 –

+2

http:// stackoverflowの重複。com/questions/8115722/generation-unique-random-numbers-in-java – Satya

+1

@nikpon 'ランダム 'の何が問題なのですか?それは完全に良いです – Dici

答えて

5

簡単な解決策は、10桁のリストを生成し、そのリストをシャッフルし、最初の5つの要素を取得することです:

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)はランダムな場所で与えられたリストを並べ替えるユーティリティメソッドです。あなたは、Java 8を使用している場合、これはのように書くことができ

:、しかし

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

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

@Tunkaiありがとうございました。しかし、ランダムを使用して一意の数値を生成する方法はありますか?私はそれが学校の割り当てなので、ランダムにしか使用できないためです。 –

+1

組み込みの方法はありません。あなたが得ることができるのは、あなたが得た数が以前に見つからなくなるまで、ループ内でランダムを使ってintを生成することです。 – Tunaki

+0

@ N.Creは私の答えを見て、それは基本的に 'Collections.shuffle'と同じアルゴリズムですが、ライブラリメソッドを使用しません。それは知っていると良いあなたの割り当てにも良いですが、現実のTunakiの答えを念頭に置いておく方が良いです。私はあなたが私のupvoted場合私は気にしないだろう:D – Dici

3

素朴なテクニックは、あなたが「シャッフル」するセットにランダムに選択することですList.removeは通常O(n)なので、全体の方法は2次式であり、非常に高価です。あなたは(つまり、Collections.shuffleが何をするかである)単に場所で要素を交換することによりO(n)でシャッフルを行うことができます。

​​3210
1

このメソッドは、範囲の中でユニークな番号の長さNのシーケンスを生成する[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; 
} 

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; 
    } 
} 
  • Ronald Fisher and Frank Yates)のおかげで、アルゴリズムの時間複雑度はこの実装は、プリミティブと(アレイ上で動作O(N)
  • あります)ではなく、コレクションにはない(オブジェクトにint型の値をラップするIntegerクラスのインスタンスを持つ) - 配列のサイズが十分大きい場合は重要
0

これは、セットを使用し、必要なサイズになるまでそれを塗りつぶす別の方法です。 numbersToDraw最小から(範囲を含む)の範囲内の異なる乱数を生成します。また、数値が描画された順序も保持されます(つまり、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; 
} 

あなたが一意であることの番号を必要としない場合、あなたは、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()); 

あなたが一意であることの番号を必要としませんが、あなたは彼らの個別の値を印刷したい場合(あなたの元の質問ということです?):

final Random randomizer = new SecureRandom(); 

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

そして、あなたの具体的なケースのための1つ以上の代替:

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