11

我想生成随机数,但不希望它们来自exclude数组。这是我的代码。

public int generateRandom(int start, int end, ArrayList<Integer> exclude) {
    Random rand = new Random();
    int range = end - start +1 - exclude.size();
    int random = rand.nextInt(range) + 1;

    for(int i = 0; i < exclude.size(); i++) {
        if(exclude.get(i) > random) {
            return random;
        }
      random++;
    }

    return random;
}

我在 while 循环中使用这个函数,并且在每次迭代期间我添加一个新值到exclude. 有时它会返回属于 的数字exclude。有什么问题?

4

5 回答 5

8

我认为有一些错误。

1) 范围应该是 end - start + 1,因为这是想要的范围。
2)如果你真的想要随机数(在计算机上尽可能“随机”),那么你不应该只得到下一个可用的数字。因为在这种情况下,您的随机数将具有排除数字密度/频率的特征。

public int generateRandom(int start, int end, ArrayList<Integer> excludeRows) {
    Random rand = new Random();
    int range = end - start + 1;
    int random;

    boolean success = false;
    while(!success) {
        random = rand.nextInt(range) + 1;
        for(Integer i: excludeRows) {
            if(i == random) {
                break;
            } else if (i > random) {
                success = true;
                break;
            }
        }
    }
    return random;
}

更新

通过 Achintya Jha 的回答,我的代码可以得到改进(但请注意,也有一些评论):

public int generateRandom(int start, int end, ArrayList<Integer> excludeRows) {
    Random rand = new Random();
    int range = end - start + 1;

    int random = rand.nextInt(range) + 1;
    while(excludeRows.contains(random)) {
        random = rand.nextInt(range) + 1;
    }

    return random;
}
于 2013-02-18T12:19:20.317 回答
6
if(!exclude.contains(random))
    return random;

每次都会尝试此操作,它将返回不排除在外的值。

于 2013-02-18T12:21:43.840 回答
2

你检查:

for(int i = 0; i < exclude.size(); i++) {
    if(exclude.get(i) > random) {
        return random;
    }

如果只有第一个更大,您将返回该值。你确定exclude是排序的?

您可以使用if(exclude.contains(random ))或以下算法:

如果(end-start)是一个合理的数字,并且您需要几乎所有值,您可以创建一个所有可接受数字的列表,并在此列表大小上使用 random 并选择随机值作为索引。然后从列表中删除不需要的数字并获得另一个随机索引。

于 2013-02-18T12:13:24.333 回答
1

这对我有用:

    public int randomInt(int start, int end, int... exception) {
        int result = -1;
        Random rand = new Random();
        int range = end - start + 1;
        boolean equals = true;

        while(equals) {
            result = rand.nextInt(range);
            boolean differentOfAll = true;
            for(int i : exception) {
                if(result==i) {
                    differentOfAll = false;
                    break;
                }
            }
            if(differentOfAll) {
                equals = false;
            }
        }

        return result;
    }
于 2019-11-15T20:11:54.447 回答
-1

实际上,我们不需要使用contains(random)while 循环。

为了简化问题,让我们看看如果我们只有一个排除值会发生什么。我们可以将结果分成2几部分。那么可能值的数量是range-1。如果随机数小于排除值,则返回它。否则,我们可以添加1.

对于多个排除值,我们可以将结果集拆分为多个size+1部分,其中size表示排除值的数量。那么可能值的数量是range-size。然后我们按升序对排除值进行排序。如果随机数小于排除值 minus i,那么我们只返回随机数 add i,其中i是排除值的索引。

public int generateRandomNumberWithExcepts(int start, int end, List<Integer> excepts) {
    int size = excepts.size();
    int range = end - start + 1 - size;
    int randNum = random.nextInt(range) + start;
    excepts.sort(null); // sort excluding values in ascending order
    int i=0;
    for(int except : excepts) {
        if(randNum < except-i){
            return randNum + i;
        }
        i++;
    }
    return randNum + i;
}
于 2017-11-10T23:18:07.043 回答