我的目标是从 0, ... n-1 中抽取 k 个整数而不重复。采样整数的顺序无关紧要。在每次调用时(经常发生),n 和 k 会略有不同,但变化不大(n 约为 250,000,k 约为 2,000)。我提出了以下摊销 O(k) 算法:
- 准备一个包含项目 0、1、2、...、n-1 的数组 A。这需要 O(n) 但由于 n 相对稳定,因此可以使成本摊销为常数。
- 从 [0:i] 中采样一个随机数 r,其中 i = n - 1。这里的成本实际上与 n 有关,但由于 n 不是非常大,因此这种依赖性并不重要。
- 交换数组 A 中的第 r 项和第 i 项。
- 将 i 减 1。
- 重复k次步骤2~4;现在我们在 A 的尾部有一个长度为 k 的随机排列。复制这个。
- 我们应该将 A 回滚到其初始状态 (0, ... , n-1) 以保持步骤 1 的成本不变。这可以通过在步骤 2 的每次通过时将 r 推入长度为 k 的堆栈来完成。堆栈的准备需要摊销的恒定成本。
我认为排列/组合的统一采样应该是一个详尽研究的问题,所以要么(1)有一个更好的解决方案,要么至少(2)我的解决方案是一个(小的修改)一个众所周知的解决方案。因此,
- 在情况(1)中,我想知道更好的解决方案。
- 在情况(2)中,我想找到一个参考。
请帮我。谢谢。