为每个数组值生成一个唯一的随机数
问题描述:
我有这种方法为此方法中列出的每个数组值生成一个数字(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];
}
答
一个简单的解决方案是产生的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();
答
一个天真的技术是在组随机挑选你想“洗牌”:
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
一样):
答
此方法生成的在范围唯一号码的长度为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());
你不应该使用随机。 – 2015-09-06 12:22:00
重复http:// stackoverflow。com/questions/8115722/generated-unique-random-numbers-in-java – Satya
@nikpon“随机”有什么问题?这非常好 – Dici