我想生成从0
到size - 1
的索引,统一但不同于给定集合excluded
中的任何索引。
size
大约为100.通常有1个,2个或3个exluded
个索引。 excluded
中的索引是唯一且未排序的。
理想情况下,标题将包含多个参数,可能是这样的:
int getRandomIndex(Random rand, int size, int... i)
或者,如果这个...
多个参数很慢(是吗?),我们可以传递简单的int[] excluded
数组等。
如何快速完成? getRandomIndex()
被称为数百万次。
答案 0 :(得分:4)
static int getRandomIndex(Random rand, int size, Integer... excludes) {
List<Integer> excludeList = Arrays.asList(excludes);
int number;
do {
number = rand.nextInt(size);
} while (excludeList.contains(number));
return number;
}
答案 1 :(得分:3)
您可以分配可能值的数组0..size-1,删除所有已知索引并从其余部分中选择随机元素。
如果索引数组已排序且所有值都是唯一的,则可以在没有中间值数组的情况下执行此操作:
int getRandomIndex(Random rand, int size, int... ii)
{
int result = rand.nextInt(size - ii.length);
for(int i : ii) {
if(result >= i) {
++result;
}
}
return result;
}
编辑:我发现如果情况有误,请更正。
编辑:
int getRandomIndex(Random rand, int size, int i) {
int result = rand.nextInt(size - 1);
if(result >= i) {
result++;
}
}
int getRandomIndex(Random rand, int size, int i, int j) {
int result = rand.nextInt(size - 2);
if(i > j) {
int tmp = j;
j = i;
i = tmp;
}
if(result >= i) {
result++;
}
if(result >= j) {
result++;
}
return result;
}
(i,j,k)的类似函数。
只调用rand.next
一次的函数可能比任何函数更快,它会多次请求随机数。
答案 2 :(得分:1)
我的做法有点不同。要选择小于大小但不是i或j的随机数,您可以选择介于0和大小为3之间的随机数。如果该数字为i,则返回size-2,如果数字为j,则返回size-1。否则返回原始随机数。
i或j的边缘情况在2的大小范围内,但我将其留给感兴趣的读者。实际上我认为它只是运作正常。
这可以推广为选择小于不在整数数组中的大小的数字。选择小于大小的数字 - 数组长度 - 1.
答案 3 :(得分:1)
您可以使用Set
快速查找
int getRandomIndex(Random rand, int size, Integer... i) {
return getRandomIndex(rand, size, new HashSet<Integer>(Arrays.asList(i)));
}
int getRandomIndex(Random rand, int size, Set<Integer> x) {
int result;
do {
result = (int) (rand.nextDouble() * size);
} while (x.contains(result));
return result;
}
如果预定义了所有索引的集合,那么您可以拥有Set
x
final static
并在每次调用方法时备用它。
<强> EIDT 强>
那么如果性能是一个问题那么我会说你的while(r == i || r == j || r == k)
的第一种方法既不坏也不丑,只需要三次重载你的方法并调用你需要的那个,调用看起来就是与val-len-array相同。
您的评估速度不能超过(r == i || r == j || r == k)
int getRandomIndex(Random rand, int size, int i)
int getRandomIndex(Random rand, int size, int i, int j)
int getRandomIndex(Random rand, int size, int i, int j, int k)
答案 4 :(得分:0)
假设许多连续呼叫使用相同的大小和排除的值......
getRandomIndex
时,只需选择此数组的随机元素代码:
int[] indices;
void init(int size, Integer... excluded)
{
indices = new int[size-excluded.length];
int pos = 0;
Set<Integer> excludedSet = new HashSet<Integer>(Arrays.asList(excluded));
for (int i = 0; i < size; i++)
{
if (!excludedSet.contains(i))
{
indices[pos++] = i;
}
}
}
int getRandomIndex(Random random)
{
return indices[random.nextInt(data.length)];
}
使用示例:
init(100, 50, 23, 10);
Random random = new Random();
for (int i = 0; i < 200; i++)
{
System.out.println(getRandomIndex(random));
}