c语言中tr1=1,C tr1 unordered_set随机唯一子集的最快方法

这篇博客介绍了一个在O(n)时间复杂度内,仅需O(1)空间的算法,用于从数字流中抽取k个均匀随机元素。算法通过维护一个概率不变量,确保每个元素都有相等的被选中机会。在每一步,算法以1/k的概率替换当前候选元素,从而在遍历完整个数据流后,得到k个随机样本。该方法适用于不知道输入集大小的情况,并且适用于C语言实现。
摘要由CSDN通过智能技术生成

根据您想要的运行时间保证,有一个着名的O(n)算法,用于在一次通过中从数字流中挑选k个随机元素.为了理解算法,让我们首先看一下我们想要从集合中选择一个元素的情况,然后我们将它概括为用于挑选k个元素.这种方法的优点是它不需要任何关于输入集大小的预先知识,并保证元素的可测量均匀采样,这总是相当不错的.

假设我们想要从集合中挑选一个元素.为此,我们将对集合中的所有元素进行传递,并且每个点都将保留我们计划返回的候选元素.当我们遍历元素列表时,我们会以一定的概率更新我们的猜测,直到最后我们选择了具有统一概率的单个元素.在每一点上,我们将保持以下不变量:

After seeing k elements,the probability that any of the first k elements is currently chosen as the candidate element is 1 / k.

如果我们在整个数组中保持这个不变量,那么在看到所有n个元素之后,每个元素都有1 / n的机会成为候选元素.因此,候选元素已经以均匀随机概率被采样.

要了解算法的工作原理,让我们考虑一下维护不变量的必要条件.假设我们刚看到第一个元素.为了保持上述不变量,我们必须以概率1选择它,因此我们将候选元素的初始猜测设置为第一个元素.

现在,当我们来到第二个元素时,我们需要保持不变量,即每个元素的概率为1/2,因为我们已经看到了两个元素.因此,假设我们选择第二个元素,概率为1/2.然后我们知道以下内容:

>我们选择第二个元素的概率是1/2.

>我们选择第一个元素的概率是我们第一次选择它的概率(1)我们不仅仅选择第二个元素(1/2)的概率.这也是1/2.

所以在这一点上,仍然保持不变量!让我们看看当我们来到第三个元素时会发生什么.此时,我们需要确保以1/3的概率挑选每个元素.好吧,假设我们以1/3的概率选择最后一个元素.然后我们就知道了

>我们选择第三个元素的概率是1/3.

>我们选择前两个元素中的任何一个的概率是在我们没有选择第三个元素(2/3)的前两个步骤(1/2)之后选择它的概率.这可以达到1/3.

再一次,不变量持有!

这里的一般模式如下所示:在我们看到k个元素之后,每个元素都有1 / k的机会被选中.当我们看到(k 1)st元素时,我们选择它的概率为1 /(k 1).这意味着它以1 /(k 1)的概率选择,并且选择它之前的所有元素的概率等于我们之前选择它的几率(1 / k)并且没有选择(k 1)st这个时间元素(k /(k 1)),它给每个元素每个选择1 /(k 1)的概率.由于这保持了每一步的不变性,我们有了一个很好的算法:

>当您看到它时,选择第一个元素作为候选元素.

>对于每个连续的元素,用概率为1 / k的候选元素替换候选元素,其中k是到目前为止看到的元素数.

这在O(n)时间内运行,需要O(1)空间,并从数据流中返回一个均匀随机的元素.

现在,让我们看看如果我们想要从集合中挑选k个元素,而不仅仅是一个,那么如何扩展它.这个想法与之前的算法非常相似(实际上最终成为更普遍的算法的特例).我们维护k个不同的候选者,而不是维持一个候选者,存储在我们编号为1,2,…,k的数组中.在每一点上,我们都保持这种不变性:

After seeing m > k elements,the probability that any of the first m elements is chosen is

k / m.

如果我们扫描整个数组,这意味着当我们完成时,每个元素都有被选择的概率k / n.由于我们选择k个不同的元素,这意味着我们随机均匀地从数组中抽取元素.

该算法与之前类似.首先,用概率1选择集合中的前k个元素.这意味着当我们看到k个元素时,它们中任何一个被挑选的概率是1 = k / k且不变量成立.现在,假设在m次迭代之后不变量成立,并考虑(m 1)st迭代.选择介于1和(m 1)之间的随机数.如果我们选择1和k之间的数字(包括),则用下一个元素替换该候选元素.否则,不要选择下一个元素.这意味着我们根据需要选择概率为k /(m 1)的下一个元素.选择前m个元素中任何一个元素的概率就是它们之前选择的概率(k / m)乘以我们没有选择包含该元素的时隙(m /(m 1))的概率,这给出了根据需要选择k /(m 1)的总概率.通过归纳,这证明该算法完美地均匀地随机地从集合中取样k个元素!

此外,运行时为O(n),它与集合的大小成比例,这完全独立于您要选择的元素数量.它也只使用O(k)存储器,并且不对存储的元素类型做任何假设.

既然你正试图为C做这个,作为一个无耻的自我推销,我在我的个人网站上实现了这个算法(写成STL算法)available here.随意使用它!

希望这可以帮助!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值