如何生成特定范围内的唯一随机数。

4
我希望生成在0-255范围内的255个唯一的随机数。这样数组就不会包含重复的记录。
short [] array =new short[255];
Random rand = new Random();
boolean   flag=false;
for (int i=0;i<array.length;i++){
    int random_integer = rand.nextInt(255-0) + 0;
    for (int j=0;j<i;j++){
        if ((short)random_integer==array[j]){
            flag=true;
        }
    }
    if (flag==false){
        array[i]=(short)random_integer;  
    }
}
for (int i=0;i<array.length;i++){
    System.out.println(array[i]);
} 

但是我只得到前20或30个具有值的项目,剩下的数组项目均为零。


4
为什么不直接生成集合中的所有值,然后再将其打乱呢? - Jon Skeet
7个回答

5

解决方案1:

我看了Jon Skeet的评论,当然,这是最简单的解决方案:

List<Integer> list = new ArrayList<>();
for (int i = 0; i < 255; i++) {
     list.add(i);
}
//and here is the point. Java already have this implemented for you
Collections.shuffle(list);

或者在Java 8中使用声明式风格:

List<Integer> list= IntStream.range(0, 255)
    .boxed()
    .collect(Collectors.toList());
Collections.shuffle(list);

或者

List<Integer> list = new ArrayList<>();
IntStream.range(0, 255).forEach(list::add);
Collections.shuffle(list);

解决方案2(参考您的解决方案):

您需要为每个单元格生成一个数字,并检查该数字是否已存在:

 short [] array =new short[255];
 Random rand = new Random();

 for (int i=0; i<array.length; i++) {
     int random_integer = -1;

     //generate integer while it exists in the array
     while(exists(random_integer, array)) {
         random_integer = rand.nextInt(255);
     }

     array[i] = random_integer;
}

现在,让我们检查它是否存在:

public boolean exists(int number, int[] array) {
    if (number == -1)
        return true; 

    for (int i=0; i<array.length; i++) {
        if (number == array[i])
            return true;
    }
    return false;
}

当然,你可以使用哈希表来加速exists()方法,从而将时间复杂度从O(n)降低到O(1)。


你不是在迭代列表时修改了 .size() 吗?应该改为 for (int i = 0; i < range; i++),对吧? - Bar
@Bar 啊,你说得对... 是的,应该是 range。 - darijan

5

如果您可以使用Java 8:

List<Integer> randIntegers = new Random().ints(1, 256).distinct().limit(255).boxed().collect(Collectors.toList());

1
public static void main(String ar[]){
short [] array =new short[255];
Random rand = new Random();
int random_integer;
boolean   flag=false;
for (int i=0;i<array.length;i++){
     random_integer = rand.nextInt();
     for (int j=0;j<i;j++){
         if ((short)random_integer==array[j]){
                 flag=true;
                 i--;
            }
      }
      if (flag==false)
        array[i]=(short)random_integer;  
}
for (int i=0;i<array.length;i++)
    System.out.print(" "+array[i]);
System.out.println();
}

1

您检查了随机数是否存在,但在循环中没有将标志重置为false,因此一旦出现第一个重复的数字,就不会再发生任何事情,因为标志始终为true。

您还应该加入类似以下内容的东西:

if ((short)random_integer==array[j]){
  flag=true;
  i--;
}

确保在跳过重复数字后重新访问数组的索引。

0
你需要在每次迭代中重置 flag 的值,或者改变你的逻辑:
       for (int j=0;j<i;j++){
                flag=false;//<--
                if ((short)random_integer==array[j]){
                    flag=true;
                }
            }

0
你考虑过创建一个 HashSet 并将你使用过的值放入其中吗? 那么你的代码应该像这样:
HashSet hs = new HashSet();
short [] array =new short[255];
Random rand = new Random();

for (int i=0;i<array.length;i++){
int random_integer = rand.nextInt(255-0);
if (!hs.contains(random_integer ))
{
array[i]=(short)random_integer;  
hs.put(random_integer);
}
else{ //generate new integer}
}

-1

如果没有适当的缩进,阅读代码会非常困难。

无论如何 - 如果 flag == true,你什么都不做。所以显然你没有填充数组中的许多位置。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接