假设int数组 a [i] = i,i = 0,1,2,...,N-1 。现在假设每个整数都与一个位相关联。我需要一个算法来统一随机选择整数子集中的整数,其整数的关联位是 0 。假设关联位为0的整数总数已在变量 T 中给出。
我有一个直接的解决方案是生成 r = rand()%T ,然后找到 r -th整数,其关联位为0(通过测试我= 0,1,...)。但是,我想知道有没有合适的算法呢?另外,如果说相关的位存储在一些长的int变量中(在我的情况下也是如此),找到相关位为0的 r -th整数将不是一件容易的事。 / p>
感谢您的投入。
答案 0 :(得分:1)
如果关联的比特是不规则的,即不能通过一个简单的公式从i
的值推导出来,那么除非预先处理,否则不能枚举r-th '0'
比特而不枚举前面的比特是不可能的。是允许的。
一个好的解决方案是预先计算一个表,该表将连续存储'0'
位条目的索引,并查找此表以查找r-th
条目。 (您也可以使用子集中的元素填充另一个数组,而不是索引表。)
索引打包位数组并不是什么大问题。假设64位long ints
,索引i
的位由表达式
(PackedBits[i >> 6] >> (i & 63)) & 1
(6
因为64 == (1 << 6)
。)
如果您确实想要按顺序找到r-th '0'
,可以通过预先计算每个long int中'0's
的数量来加快搜索速度(x 64),以便您可以跳过一次性64个条目。
如果你真的不想预先计算任何东西,你仍然可以通过使用与每个字节值相关的静态表(256
之间的位来处理8位8来加速搜索。 )到其中'0'
位的数量。 (如果你能负担得起使用65536
数字的表格,那么即使是16比16。)
答案 1 :(得分:0)
你可以通过交换记忆来提高速度。
T必须是一个数组,它在T [n]中存储[]中有位n清零的整数个数,这需要在某个时刻进行预计算。因此,在计算时,存储在另一个二维数组中清除了给定位的所有整数的索引,由位数和r索引。
以C为例:
#define BITS (64)
#define N (100)
long int a[N];
int T[BITS];
int index[BITS][N];
void init()
{
int i, j;
// clear T:
for(j = 0; j < BITS; j++)
T[j] = 0;
// compute T and the indices for each:
for(i = 0; i < N; i++)
{
for(j = 0; j < BITS; j++)
{
if((a[i] & (1 << j)) == 0)
{
// increment T and store the index
index[j][T[j]++] = i;
}
}
}
}
然后你可以找到这样的随机数:
long number = N[index[bit][rand() % T[bit]];
你可以通过使用一个浪费较少的数据结构来提高内存效率,这种结构只为每个位存储尽可能多的索引,因为[]中的实际值会清除这些位。
答案 2 :(得分:0)
如果T
足够大,最有效的解决方案是随机选择一个最大为N
的整数并循环,直到满足条件。