为每个数组值生成一个唯一的随机数

问题描述:

我有这种方法为此方法中列出的每个数组值生成一个数字(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

你不应该使用随机。 – 2015-09-06 12:22:00

+2

重复http:// *。com/questions/8115722/generated-unique-random-numbers-in-java – Satya

+1

@nikpon“随机”有什么问题?这非常好 – Dici

一个简单的解决方案是产生的10位数字的列表,随机播放某个列表,并获得所述第一五行:

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,这可以写为:

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

没有内置的方式。你可以做的是在循环中使用Random生成一个int,直到你之前没有找到你已经获得的数字。 – Tunaki

+0

@ N.Cre看到我的答案,它基本上与'Collections.shuffle'算法相同,但不使用库方法。这是很好的知道,也是对你的任务有好处,但请记住,在现实生活中,Tunaki的答案会更好。我不介意你是否赞成我的做法:D – Dici

一个天真的技术是在组随机挑选你想“洗牌”:

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.remove通常是O(n),所以整个方法是二次的,这是非常昂贵的。可以在通过O(n)简单地交换元件在适当位置执行的混洗(这就是Collections.shuffle一样):

​​3210

此方法生成的在范围唯一号码的长度为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)
  • 此实现适用于阵(图元)不在集合上(Integer类的实例在对象中包装基本类型int的值) - 如果数组大小足够大,这很重要

这是一个使用一套并填充它,直到它增长到所需的大小的替代方法。它生成numbersToDraw不同的随机数字,范围从分钟max(含)。它还保留了绘制数字的顺序(这就是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()); 

并为您的具体情况多了一个选择:

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