或多或少与this question相同,但选择的容器尽可能通用(即只有Forward Container或者甚至只是一个简单的Container)不应该假设容器有一个.size()并且走两次(一次计算大小并再次得到结果集)是不可接受的。
我有一个解决方案,它比我想要的更复杂一些,所以我希望在3-5行范围内有一些东西。
答案 0 :(得分:2)
我假设'随机元素'表示元素均匀分布。
由于您不知道序列的长度,并且您无法事先计算它,因此您必须逐渐构建随机序列。所以,让我们这样做,并希望我们使用的概率加起来很好,所以我们最终得到了我们想要的东西。
我们将分两步完成。首先,决定绘制哪个序列号,然后如果需要,我们可以为它们选择随机顺序(从问题中不清楚)。而且我会叫你的'N'K',因为它对我来说更容易。
首先,我们创建一个K元素数组,以保存K个绘制的元素。我们遍历序列的前K个元素并将它们复制到数组中。如果序列没有K个元素,我们会说“不能做”。
现在我们知道我们有来自K大小序列的K个随机元素。如果我们处于序列的最后,我们就完成了。如果没有,我们知道我们有一个K + 1大小的序列。这里有两个选项,选择K + 1项,或者不选择。
选择第K + 1项的概率是多少?我发现更容易计算出第K + 1项不被选中的概率。如果K + 1的元素没有出现,则有(K + 1个K)方式从K + 1中选择K个元素,并且只有(K over K)方式选择K个元素。因此(K over K)/(K + 1 over K)是第K + 1项未被选中的概率。
因此,选择0到1之间的随机数,如果小于1 /(K + 1),则第K + 1个元素不会出现在序列中。如果随机数大于该值,则第K + 1个元素确实出现在序列中。选择介于1和K之间的随机元素,并将其替换为第K + 1个元素。
现在我们转到下一个项目,第K + 2项。我们再次做同样的事情。第K + 2项未出现在序列中的概率是(K + 1对K)/(K + 2对K)。
直到序列耗尽为止。然后你有一个从序列中随机选择的K个元素的列表。
请注意,它们不是随机排序的(至少不是短序列),因此您可能希望为此选择随机K大小的排列。
免责声明:概率是一个婊子,虽然这对我来说似乎是正确的,但我有可能错过了某些东西,最终结果将无法均匀分布。其他人会很快说出来。