如何做一个随机而独特的发电机?

时间:2010-05-11 16:32:26

标签: java arrays random

我已经编写了一个随机生成器,它接受参数a和b,其中a是最小值,b是最大值,就像这个randomGenerator(int a,int b)

接下来我要做的是:使用循环,然后从a到b生成唯一编号。例如:

I want to have 8 unique numbers,
int a = 1;
int b = 10;
int value;

如果我进行循环,则会有一个很高的%,相同的数字会出现多次。知道怎么做吗?

我自己的方式是:

while(int i <= 8){
  randomGenerator(a,b);
  // if value is not in array, then insert into array
}

我被困在评论部分。有没有办法检查数组中是否存在变量?

编辑,根据nailxx的回答,我理解的是:

  • 从a到b取列表(如果按照我的例子,1 - 10)

  • “shuffle”it

  • 取前8项。这是你的意思吗?

在java世界中,是否有“shuffle”功能或者我需要创建自己的功能?

7 个答案:

答案 0 :(得分:9)

列出包含从ab的顺序分发的元素的列表,将其随机播放并在每个请求中返回带有后续索引的元素。

答案 1 :(得分:0)

由于样本的大小几乎与你的愤怒大小相同,你可以生成1到10之间的所有整数,shuffle them然后获取前8个元素。

如果样本大小(k)远小于范围大小(n),您可以使用Fisher-Yates shuffle上的变体,在k步后停止算法,而不是整个阵列。

如果样本量很小但范围大小[0,n]太大而无法存储在内存中,那么您可以使用另一种变体,在[0,n)中首先选择一个随机数s1。然后你在[0,n-1)中选择一个数字,如果它等于或大于s1,则给它加一个,给出s2。然后在[0,n-2]中选择一个数字,并为s1,s2中的每一个添加一个数字,大于或等于等等......

答案 2 :(得分:0)

如果您的想法是获取8个随机数,您可以始终使用字典/散列或List(具有Contains(int i)方法),然后将Dictionary或List转换为数组:

List<int> x = ...;
int[] data = x.ToArray();

答案 3 :(得分:0)

List<Integer> list=new ArrayList<Integer>(8);

while(int i <= 8){ 
  do {
    Integer n=randomGenerator(a,b); 
  } while (list.contains(n))
  list.add(n);
} 

当然,如果a和b之间不存在至少8个不同的值,则会陷入无限循环。在开始之前我会为它设置一个陷阱。

只有8个值,一个简单的ArrayList可能是最容易使用的东西。如果你有数百或数千个值,那么为每个新条目运行所有这些值可能会令人望而却步,你可能想要做一些更复杂的事情,比如使用HashMap,或者保留一个单独的数组标记,表示使用了什么值,或者其他一些。

答案 4 :(得分:0)

如果您的范围很小(或接近您要选择的元素数量),上面提出的解决方案就可以了。

如果您的范围变大,那么更有效(也更清晰)的方法如下:


    int[] pickRandom(int numberOfChoices, int lowerBound, int upperBound) {
      Set<Integer> choices = new HashSet<Integer>();
      while (choices.size() <= numberOfChoices) {
        choices.add(yourRandomGenerator (lowerBound, upperBound));
      }
      int[] ret = new int[choices.size()];
      int ii=0;
      for (Integer choice: choices) {
        ret[ii++] = choice.intValue();
      }
      return ret;
    }

答案 5 :(得分:0)

这里有一些很好的答案,但我会添加一个重要的警告:不要使用List,请使用HashSet。除掉我的计算机科学书呆子术语,检查列表中是否已存在元素在O(n)时间内运行;使用HashSet做同样的事情会给你O(lg n)性能,这会更快。对于一个小数据集(如1到10之间的8个数字),它是微不足道的。对于大型数据集,它可以有所作为。

这样的事情应该这样做:

    HashSet resultSet = new HashSet();
    while (resultSet.size() < targetSize) {
       resultSet.add(randomGenerator(a,b));
    }

...在您的先决条件下进行健全性检查,以确保您的目标尺寸不超过您的范围。

如果订单很重要,请在使用List确认它是新号码后将其粘贴到HashSet。或者只是将HashSet转储到新的List并随机播放。

答案 6 :(得分:0)

Collections类中有一个内置的shuffle函数。

e.g。


List values = new ArrayList();

for( int i = 1; i < 10; i++ ) {
    values.add(i);
}

Collections.shuffle(values);