Java生成唯一随机整数数组

5
public static int[] uniqueRandomElements (int size) {

    int[] a = new int[size];

    for (int i = 0; i < size; i++) {
        a[i] = (int)(Math.random()*10);

        for (int j = 0; j < i; j++) {
            if (a[i] == a[j]) {
                a[j] = (int)(Math.random()*10);
            }
        }   
    }

    for (int i = 0; i < a.length; i++) {
        System.out.print(a[i]+" ");
    }
    System.out.println();
    return a;
}

我有一个方法,应该生成由用户指定的随机元素数组。随机生成的整数应在0到10之间(包括0和10)。我可以生成随机整数,但是我的问题是如何检查唯一性。我尝试在上面的代码中检查唯一性,但数组仍然包含重复的整数。我做错了什么?有人能给我提示吗?

3
size > 10 时会发生什么?你如何为每个索引生成唯一的数字? - Jeffrey
10个回答

19
for (int i = 0; i < size; i++) {
    a[i] = (int)(Math.random()*10);

    for (int j = 0; j < i; j++) {
        if (a[i] == a[j]) {
            a[j] = (int)(Math.random()*10); //What's this! Another random number!
        }
    }   
}

你找到了重复的数值,但你将它替换为另一个可能是重复的随机数。相反,尝试这样做:

for (int i = 0; i < size; i++) {
    a[i] = (int)(Math.random()*10);//note, this generates numbers from [0,9]

    for (int j = 0; j < i; j++) {
        if (a[i] == a[j]) {
            i--; //if a[i] is a duplicate of a[j], then run the outer loop on i again
            break;
        }
    }  
}

然而,这种方法效率较低。我建议先制作一个数字列表,然后随机排列:

ArrayList<Integer> a = new ArrayList<>(11);
for (int i = 0; i <= 10; i++){ //to generate from 0-10 inclusive. 
                               //For 0-9 inclusive, remove the = on the <=
    a.add(i);
}
Collections.shuffle(a);
a = a.sublist(0,4);
//turn into array

或者你可以这样做:

ArrayList<Integer> list = new ArrayList<>(11);
for (int i = 0; i <= 10; i++){
    list.add(i);
}
int[] a = new int[size];
for (int count = 0; count < size; count++){
    a[count] = list.remove((int)(Math.random() * list.size()));
}

2

如果使用一个顺序数组并对其进行洗牌,可能会更快。然后它们都将根据定义是唯一的

请查看数组的随机洗牌以及Collections.shuffle函数。

int [] arr = [1,2,3,.....(size)]; //this is pseudo code

Collections.shuffle(arr);// you probably need to convert it to list first

1
你可能需要吗?你肯定需要转换成列表。 - Justin

1
如果您有一个重复项,只需生成相应的数字一次。但这可能会创建另一个副本。您的重复项检查代码应该被包含在一个循环中:
while (true) {
    boolean need_to_break = true;
    for (int j = 0; j < i; j++) {
        if (a[i] == a[j]) {
            need_to_break = false; // we might get another conflict
            a[j] = (int)(Math.random()*10);
        }
    }
    if (need_to_break) break;
}   

但一定要确保 size 小于 10 ,否则你会得到一个无限循环。

编辑:虽然上面的方法解决了问题,但它不够高效,不应用于大型数组。此外,这样做没有对所需完成的迭代次数进行担保上限。

一个更好的解决方案(遗憾的是只解决了第二个问题)可能是生成一系列你想要生成的不同数字(10 个数字),随机排列这个序列,然后仅选择该序列中的前 size 个元素并将其复制到您的数组中。您将为时间边界提供保证而交换一些空间。

int max_number = 10;
int[] all_numbers = new int[max_number];
for (int i = 0; i < max_number; i++)
    all_numbers[i] = i;

/* randomly permute the sequence */
for (int i = max_number - 1; i >= 0; i--) {
    int j = (int)(Math.random() * i); /* pick a random number up to i */

    /* interchange the last element with the picked-up index */
    int tmp = all_numbers[j];
    all_numbers[j] = a[i];
    all_numbers[i] = tmp;
}

/* get the a array */
for (int i = 0; i < size; i++)
    a[i] = all_numbers[i];

或者,您可以创建一个带有相同数字的 ArrayList,并且不使用中间循环,而是可以在其上调用 Collections.shuffle()。然后仍然需要第三个循环将元素放入 a 中。

我很感谢你的回答,但是我对Java的经验不足,无法理解你的回答。 - AvP
哎呀,有没有一个Java编译器可以让你使用“break”作为变量名? - ajb
谢谢,我已经好几年没有编写Java代码了,所以忘记了 :) - Mihai Maruseac
@MihaiMaruseac 没有太多的编程语言可以让你使用与关键字名称相同的变量名。我想无论在哪种语言中,if (break) break; 都应该是一个警告标志... :) - ajb
我是Haskell程序员 :) - Mihai Maruseac

0
输入大小并使用 Collections 获取随机唯一数字列表。
public static ArrayList<Integer> noRepeatShuffleList(int size) {
    ArrayList<Integer> arr = new ArrayList<>();
    for (int i = 0; i < size; i++) {
        arr.add(i);
    }
    Collections.shuffle(arr);
    return arr;
}

深入解释Karthik的答案。

0
 import java.util.Scanner;
 class Unique
{
public static void main(String[]args)
{
    int i,j;
    Scanner in=new Scanner(System.in);
    int[] a=new int[10];
    System.out.println("Here's a unique no.!!!!!!");
    for(i=0;i<10;i++)
    {
        a[i]=(int)(Math.random()*10);
        for(j=0;j<i;j++)
        {
            if(a[i]==a[j])
            {
                i--;

            }
        }   
    }
    for(i=0;i<10;i++)
    {
        System.out.print(a[i]);
    }
}
}

0
int[] a = new int[20];

for (int i = 0; i < size; i++) {
    a[i] = (int) (Math.random() * 20);

    for (int j = 0; j < i; j++) {
        if (a[i] == a[j]) {
            a[i] = (int) (Math.random() * 20); //What's this! Another random number!
            i--;
            break;
        }
    }
}

0
你可以尝试这个解决方案:
public static int[] uniqueRandomElements(int size) {
    List<Integer> numbers = IntStream.rangeClosed(0, size).boxed().collect(Collectors.toList());
    return Collections.shuffle(numbers);
}

0

如果您不想为ArrayList的额外开销付费,可以使用数组并使用Knuth shuffle

public Integer[] generateUnsortedIntegerArray(int numElements){
    // Generate an array of integers
    Integer[] randomInts = new Integer[numElements];
    for(int i = 0; i < numElements; ++i){
        randomInts[i] = i;
    }
    // Do the Knuth shuffle
    for(int i = 0; i < numElements; ++i){
        int randomIndex = (int)Math.floor(Math.random() * (i + 1));
        Integer temp = randomInts[i];
        randomInts[i] = randomInts[randomIndex];
        randomInts[randomIndex] = temp;
    }
    return randomInts;
}

以上代码生成numElements个连续整数,以均匀随机的顺序进行洗牌,且不重复。


0
    int[] a = new int [size];

    for (int i = 0; i < size; i++) 
    {
        a[i] = (int)(Math.random()*16); //numbers from 0-15
        for (int j = 0; j < i; j++) 
        {
            //Instead of the if, while verifies that all the elements are different with the help of j=0
            while (a[i] == a[j])
            {
                a[i] = (int)(Math.random()*16); //numbers from 0-15
                j=0;
            }
        }
    }

    for (int i = 0; i < a.length; i++)
    {
        System.out.println(i + ".   " + a[i]);
    }

1
不鼓励仅提供代码的答案。请添加一些解释,说明如何解决问题,或者这与现有答案有何不同。来自审核 - Nick

0
//Initialize array with 9 elements
int [] myArr = new int [9];
//Creating new ArrayList of size 9
//and fill it with number from 1 to 9
ArrayList<Integer> myArrayList = new ArrayList<>(9);
    for (int i = 0; i < 9; i++) {
        myArrayList.add(i + 1);
        }
//Using Collections, I shuffle my arrayList
Collections.shuffle(myArrayList);
//With for loop and method get() of ArrayList
//I fill my array
for(int i = 0; i < myArrayList.size(); i++){
    myArr[i] = myArrayList.get(i);
    }

//printing out my array
for(int i = 0; i < myArr.length; i++){
    System.out.print(myArr[i] + " ");
        }

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