是否有一种简单的方法可以生成随机顺序大小为n * n(例如64)和n(e.q 8)数为1的随机BitSet?
我曾经想过的是,我可能会生成一个随机的bitset,并检查bitSet.cardinality()是否为8,如果没有则再次尝试,但这似乎是一个性能不佳的解决方案。
任何人都有更好的主意吗?
答案 0 :(得分:4)
使用reservoir sampling,可以在O(N)时间内完成:
public static BitSet randomBitSet(int size, int cardinality, Random rnd) {
if (0 > cardinality || cardinality > size) throw new IllegalArgumentException();
BitSet result = new BitSet(size);
int[] chosen = new int[cardinality];
int i;
for (i = 0; i < cardinality; ++ i) {
chosen[i] = i;
result.set(i);
}
for (; i < size; ++ i) {
int j = rnd.nextInt(i+1);
if (j < cardinality) {
result.clear(chosen[j]);
result.set(i);
chosen[j] = i;
}
}
return result;
}
答案 1 :(得分:3)
获取0到63之间的8个不同的随机数。将这些位设置为1。
你的方法并不能确保8个1,每个64位的平均值为8 1(如果重复的次数足够多)。
答案 2 :(得分:1)
创建您要选择的数字列表,例如从0到63。
随机播放列表。
将第一个n
位设置为1,例如第8个。
这将具有O(n ^ 2)时间复杂度。
另一种方法是创建一个BitSet并保持设置随机清零位,直到总共设置为8。你不需要测试基数。
int n = ...
Random rand = new Random();
BitSet bs = new BitSet(n * n);
for(int i = 0; i < n; i++) {
int j = rand.nextInt(n * n);
if (bs.get(j))
i--;
else
bs.set(j);
}
这通常略差于O(n)
答案 3 :(得分:1)
设置一个字符数组:{1 1 1 1 1 1 1 0 0 ... 0 0 0},正确的数字为1和0。
使用Fisher-Yates算法对字符数组进行随机随机播放。
将混洗数组转换为BitSet。无论何处出现'1'字符,都将相应位设置为0b1。所有其他位可以设置为0b0。
ETA:考虑一下,你可以直接创建和改组BitSet。基础算法仍然是相同的。