Java 生成一定范围内不重复的随机数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21213577/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 07:22:30  来源:igfitidea点击:

Generate random number without duplicate in certain range

javaalgorithmrandomrange

提问by amln_ndh

I'm currently creating an app and it will generate random numbers. So each time it will generate three numbers num1, num2 and num3. These number should not be duplicate. For example if num1 = 1 than num2 and num3 cannot be equal to 1. I've tried this code where it will display three different number ranging from 0-2. And its working. However I would want to generate random number ranging from 1-3, 2-4, 3-5 and so on. So how can I achieve this by using the code below. Please help me since I'm new to this. Thank you.

我目前正在创建一个应用程序,它将生成随机数。所以每次它都会生成三个数字 num1、num2 和 num3。这些号码不应重复。例如,如果 num1 = 1 比 num2 和 num3 不能等于 1。我试过这段代码,它将显示三个不同的数字,范围从 0 到 2。它的工作原理。但是,我想生成 1-3、2-4、3-5 等范围内的随机数。那么我如何通过使用下面的代码来实现这一点。请帮助我,因为我是新手。谢谢你。

for(int i=0; i<images.length; i++)
{
        num[i] = (int)(Math.random()*3);

        if (i == 0)
        {
        if(num[i]== 0)
            images[i].setImageResource(R.drawable.zero);
        else if(num[i]==1)
            images[i].setImageResource(R.drawable.one);
        else
            images[i].setImageResource(R.drawable.two);
        }

        else
        {
            while (num[i] ==  num[i-1] || num[i] == num[0] )
                num[i] = (int)(Math.random()*3);


        if(num[i]==0)
            images[i].setImageResource(R.drawable.zero);
        else if(num[i]==1)
            images[i].setImageResource(R.drawable.one);
        else
            images[i].setImageResource(R.drawable.two);

        }
    }

回答by Little Child

Well, you could store your numbers an an ArrayList<>. Every time you generate a random number, see if the ArrayList<>contains the number. If it does, generate another number and repeat the process.

好吧,您可以将您的数字存储为 an ArrayList<>。每次生成随机数时,查看是否ArrayList<>包含该数字。如果是,则生成另一个数字并重复该过程。

Better yet, use a Set <>.

更好的是,使用Set <>.

回答by LMNOP

To get numbers ranging from 1-3, 2-4, 3-5, etc, change this

要获得 1-3、2-4、3-5 等范围内的数字,请更改此

num[i] = (int)(Math.random()*3);

to this

对此

num[i] = rand.nextInt(2) + 1 + i;

You'll need to import Randomand add Random rand = new Random();before using it.

在使用它之前,您需要导入Random和添加Random rand = new Random();

回答by Vikas Rathod

The formula to generate random number in the range is :

生成范围内随机数的公式为:

    Random rn = new Random();
    int range = maximum - minimum + 1;
    int randomNum =  rn.nextInt(range) + minimum;

so in one line you can generate as like this

所以在一行中你可以像这样生成

    int num1 = new Random().nextInt(3-1+1) + 1;
    int num2 = new Random().nextInt(4-2+1) + 1;
    int num3 = new Random().nextInt(5-2+1) + 1;

or

或者

    num[i] = new Random.nextInt(range[i]) + 1 + i;

and then you can do your logic stuff to set the resource. Happy Coding :)

然后你可以做你的逻辑东西来设置资源。快乐编码:)

回答by ucsunil

The best possible and most efficient way to generate and store unique numbers would be to create a HashSet that holds your data. Generate the number and then try to add it to the HashSet. If the add method returns false, then it means that the number already exists in the set and hence re-generate a number. The advantage of using this method over the ArrayList is that this has a time complexity of O(1) while using the contains() method (from ArrayList) would result in a time complexity of O(n) - efficiency decreases as size increases.

生成和存储唯一数字的最好和最有效的方法是创建一个 HashSet 来保存您的数据。生成数字,然后尝试将其添加到 HashSet。如果 add 方法返回 false,则表示该数字已存在于集合中,因此重新生成一个数字。使用此方法相对于 ArrayList 的优势在于,它的时间复杂度为 O(1),而使用 contains() 方法(来自 ArrayList)将导致时间复杂度为 O(n) - 效率随着大小的增加而降低。

回答by Bohemian

Create a list if all numbers in the range, then shuffle the list:

如果范围内的所有数字都创建一个列表,然后将列表打乱:

List<Integer> numbers = new ArrayList<>();
// eg for range 3-5
for (int i = 3; i <= 5; i++)
    numbers.add(i);
Collections.shuffle(numbers);

Now use them in their new (random) order.

现在以新的(随机)顺序使用它们。

Unless your range is very large (millions) this will work fine.

除非您的范围非常大(数百万),否则这将正常工作。



Java8 version:

Java8版本:

List<Integer> numbers = IntStream.rangeClosed(3, 5).boxed().collect(Collectors.toList());
Collections.shuffle(numbers);

回答by alesc3

int base = (int)Math.random();System.out.print(base);

int base = (int)Math.random();System.out.print(base);

int change = ((int)Math.random()) % 3;

int change = ((int)Math.random()) % 3;

if(change == 0) {change++;System.out.print(base + 1);System.out.println(base + 2);}

if(change == 0) {change++;System.out.print(base + 1);System.out.println(base + 2);}

else {System.out.print(base + 2);System.out.println(base + 1);}

else {System.out.print(base + 2);System.out.println(base + 1);}

回答by akkig

You can also use Random number generation to fill a HashSet for a fixed range.

您还可以使用随机数生成来填充固定范围的 HashSet。

回答by Suresh

Integer[] a = new Integer[3];
Random r = new Random();
for (int i = 0; i < a.length; i++) { 
        a[i] = r.nextInt(3-1) + 1;  
}
Collections.shuffle(Arrays.asList(a), r);

回答by Addis

I know it's late, but could be helpful for future reference. You can create your own custom Random class:

我知道现在已经晚了,但可能对将来的参考有所帮助。您可以创建自己的自定义 Random 类:

//Generates random integers without repetition between two given numbers both inclusive
public class Random {
    private int start;
    private int end;
    private Stack<Integer> numbers = new Stack<>();
    public Random(int start, int end){
        this.start = start;
        this.end = end;
    }
    private void loadNumbers(){
         for (int i=start;i<=end;i++){
                numbers.push(i);
            }
         Collections.shuffle(numbers);
    }
    public int nextInt(){
        if (numbers.empty()) loadNumbers();
        return numbers.pop();
    }
}

And use it like:

并像这样使用它:

Random rand = new Random(1,20);
for(int i=0; i<100;i++){
    System.out.print(rand.nextInt()+ " ");
}

回答by SOFe

Reduce the total amount every run, and appropriately increment the result.

减少每次运行的总量,并适当增加结果。

static int[] randomRange(Random random, int cap, int count) {
    assert count < cap && count > 0 && cap > 0;
    int[] output = new int[count];
    // initial placeholder. use 0x7FFFFFFF for convenience is also OK.
    Arrays.fill(output, -1);
    for(int i = 0; i < count; i++) {
        // you only have (cap - i) options left
        int r = random.nextInt(cap - i);
        // iterate through a sorted array
        for(int got : output) {
            // ignore placeholders
            if(got != -1 && got <= r) {
                // the generated random int counts number of not-yet-picked ints
                r++;
            }
        }
        // add to array in a sorted manner
        addToArray(output, r);
    }
    return output;
}

static void addToArray(int[] array, int value) {
    for(int i = 1; i <= array.length; i++) {
        if(i == array.length || array[i] >= value) {
            // shift smaller values one place left
            // this includes -1. If you use 0x7FFFFFFF,
            // you may have to sort the array the other way round.
            System.arraycopy(array, 1, array, 0, i - 1);
            array[i - 1] = value;
            return;
        }
    }
}

This algorithm has a disadvantage that its output is sorted. It is, of course, also possible to keep track of two arrays, one sorted (for increment) and one unsorted (for return).

该算法的缺点是其输出是排序的。当然,也可以跟踪两个数组,一个已排序(用于增量)和一个未排序(用于返回)。

The above code snippet was tested through cap = 20, count = 10and cap = 20, count = 20twice each.

上面的代码片段经过了测试cap = 20, count = 10cap = 20, count = 20每个都测试了两次。