【问题标题】:Data structure for choosing random elements?选择随机元素的数据结构?
【发布时间】:2010-12-30 18:00:43
【问题描述】:

有人知道有效支持这两种操作的数据结构吗?

  1. 在数据结构中插入一个值。
  2. 出列并以均匀随机概率从数据结构中返回一个条目。

这有点像经典的“弹珠袋”,总是出现在介绍性概率类中。您可以将任意弹珠放入袋中,然后可以高效地随机取出弹珠。

我的最佳解决方案如下 - 使用自平衡二叉搜索树(AVL、AA、红/黑等)来存储元素。这给出了 O(lg n) 的插入时间。要删除一个随机元素,请选择一个随机索引 i,然后从树中定位并删除第 i 个元素。如果你适当地扩充了结构,也可以在 O(lg n) 时间内运行。

这个运行时当然不错,但我很好奇是否有可能做得更好——也许插入 O(1) 和出队 O(lg n)?或者也许在 expected O(1) 使用散列函数插入和删除中运行的东西?或者可能是更强的摊销界限?

有没有人知道如何使这个渐近更快?

【问题讨论】:

  • 只是出于好奇:有人知道这个数据结构是否有名字吗?这显然是Bag 和/或MultiSet 的一种。 RandomBag,也许吧?实际上,一般称为的这种数据结构(即pop返回并删除随机元素的数据结构)是什么?
  • 我听说过这里使用的 Bag 和 RandomBag 这两个术语,但我认为 RandomBag 可能是合适的术语; Bag 通常是 multiset 的同义词。

标签: algorithm language-agnostic data-structures random


【解决方案1】:

是的。使用向量。

要插入,只需放在末尾,然后增加大小。要删除,请随机选择一个元素,将其内容与结束值交换,然后弹出结束值(即,返回结束值并减小向量的大小)。

这两个操作的摊销时间为 O(1)。

【讨论】:

  • 当你不需要保持秩序的时候,数据结构就是这么简单:)
  • 漂亮!这是一个很棒的解决方案。非常感谢!
  • @templatetypedef:我很高兴。 :-) 顺便说一句,如果你申请谷歌,你应该知道这个方法基本上是 Fisher-Yates shuffle 的变体。除了将洗牌后的值保留在数组中之外,您将它们全部提取出来。 :-P
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-18
相关资源
最近更新 更多