【问题标题】:Take always a different random element in range总是在范围内取一个不同的随机元素
【发布时间】:2016-04-27 17:22:58
【问题描述】:

我需要选择两个不同的整数,它们属于某个范围[min, max]

示例rds = 3min = 0max = 9。如果第一个随机元素是r1 = 6,那么r2必须不同于6r3必须不同于r1r2

我想构建一个包含所有属于[min, max] 的数字的数组:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

我在09 之间选择一个随机数并返回ThreadLocalRandom.current().nextInt(0, 10),然后我交换r1 和数组的最后一个元素。 为了找到r2,我将0中的随机函数应用到数组中的倒数第二个位置,依此类推。

这是代码:

public void takeRandomXposition(int rds, int[] positions) { 
    int k = positions.length;
    int min = 0;
    int max = k - 1;
    for(int i = 0; i < rds; i++) {
        int r = random(positions[min], positions[max - i]);
        swapPositions(positions, r, max - i);
    }
}

public int random(int min, int max) {
    return ThreadLocalRandom.current().nextInt(min, max + 1);
}

public void swapPositions(int[] positions, int index, int last) {
    int indexA = positions[index];
    int lastA = positions[last];
    positions[index] = lastA;
    positions[last] = indexA;
}

此方法适用于第一步,但不再适用。 问题是数组中的元素被移动和混合,但我尝试了一个范围内的随机数。 不知道怎么解释,我举个例子说明方法不行。

positions: [ 0 1 2 3 4 5 6 7 8 9 ]
rds = 3
k = 10
min = 0
max = 9

    i = 0
    search r in range [0, 9]
    r = 5
    positions: [ 0 1 2 3 4 9 6 7 8 5 ]

    i = 1
    search r in range [0, 8]
    r = 3
    positions: [ 0 1 2 8 4 9 6 7 3 5 ]

    i = 2
    search r in range [0, 7]
    r = 5
    positions: [ 0 1 2 8 4 7 6 9 3 5 ]

另外r = 0时还有一个问题:

positions: [ 0 1 2 3 4 5 6 7 8 9 ]
rds = 3
k = 10
min = 0
max = 9

    i = 0
    search r in range [0, 9]
    r = 0
    positions: [ 9 1 2 3 4 5 6 7 8 0 ]

    i = 1
    search r in range [9, 8]
    Exception in thread "main" java.lang.IllegalArgumentException: bound must be greater than origin

所以,我不想在[min, max] 范围内找到一个随机数,而是在一个数组的内容中找到一个随机数。

谢谢。

【问题讨论】:

  • 为什么不使用简单的数学公式创建一个表示特定范围内数组的数字(索引)的方法(以控制 indexOutOfBoundException)?!
  • @MR1 对不起,我没明白你的意思。
  • 据我了解您的问题,您希望随机访问数组的内容,为此您需要访问数组的特定元素,因此通过指定该方法,您可以访问随机元素数组。

标签: java arrays random


【解决方案1】:

将生成的随机数存储在一个列表中并继续生成,直到找到不在列表中的随机数。

LinkedList<Integer> list = new LinkedList<>();
final int min = 0;
final int max = 10;

while(list.size() < max) // Condition to not keep iterating forever
{
    do 
    {
        int random = ThreadLocalRandom.current().nextInt(min, max + 1);

    } while (list.contains(random));

    list.add(random);
}

您也可以使用数组的方法,就像您尝试做的那样

int min = 0;
int max = 10;
int array[] = new int[max + 1];

int filledArray = 0;

while(filledArray < max + 1) // Condition to not keep iterating forever
{
    do 
    {
        int random = ThreadLocalRandom.current().nextInt(min, max + 1);

    } while (array[random] == 1);

    array[random] = 1;
    filledArray++;
}

编辑:我不完全确定这是否是您正在寻找的。我的理解是,你想在给定范围内找到随机数,而不是得到两次相同的随机数

【讨论】:

  • 是的,你明白了。我认为您建议的方式很好,但恐怕它表现不佳。例如,如果我必须在 [0, 9] 范围内生成 5 个随机数,以创建最终数字,则该方法应该在 while 循环内相当多。我是对的?
  • @marielle 不是真的。在第一种方法中(使用列表),将外部while 条件替换为list.size() &lt; 5。当循环结束时,在列表中,您将在给定范围内拥有 5 个不同的随机数。数组几乎相同,您只需添加一个存储生成数字的列表,或者遍历数组以检查哪些位置有 1
  • 谢谢,Nadir,我使用了你的第一种方法。
【解决方案2】:

听起来您可能想要随机播放。您可以通过将整个过程包装在一个类中来简化它。

class NonRepeatingRandomNumberGenerator {

    List<Integer> numbers = new ArrayList();
    int index = 0;

    public NonRepeatingRandomNumberGenerator(int min, int max) {
        for (int i = min; i <= max; i++) {
            numbers.add(i);
        }

        Collections.shuffle(numbers);
    }

    public int getNext() {
        // If your range has 5 numbers and you want 7 you will have to repeat at some point
        if (index == numbers.size()) {
            index = 0;
            Collections.shuffle(numbers);
        }

        return numbers.get(index++);
    }
}


// Usage
NonRepeatingRandomNumberGenerator rng = new NonRepeatingRandomNumberGenerator(10, 42);
rng.getNext();
rng.getNext();
rng.getNext();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-23
    • 1970-01-01
    • 1970-01-01
    • 2018-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多