【问题标题】:Which data structure to use as Stack with random position insertion ability?哪种数据结构用作具有随机位置插入能力的 Stack?
【发布时间】:2016-01-18 16:49:20
【问题描述】:

纸牌游戏,用过的纸牌回到牌组,但不插入底部,而是在牌组第二半的随机位置

例如给定一副牌[c5, c6, c7, c8, c9] 下一个pop 操作应该返回c5,并且在使用c5 之后,它应该在第二半内重新插入到卡组中,
即在c8 之前或c8 之后或c9 之后

你会如何为这套牌设计一个高效的数据结构?

卡片数量不变

【问题讨论】:

  • 我能想到的最好的就是一个基于链表的栈,但是对于每个pop来说这将是O(n)(因为这里的pop实际上是一个pop+insert)
  • 弹出将是 O(1),因为我可以将 ref 保持在头部,但插入到中间将是 O(n)
  • 没错,在这里,因为 pop 将是 pop+insert,所以 O(1)+O(n) :(
  • 为了进一步优化插入,他可以保留一个指向堆栈中间的指针,并在执行弹出时将其向前移动,然后从该指针开始插入查找。它会将插入更改为 O(n/2),仍然是 O(n),但从技术上讲要快一些。

标签: data-structures


【解决方案1】:

如果卡片的数量真的总是 52,那么数组就是一个很好的数据结构。由于元素的数量是恒定的,所有的操作都是恒定的时间。在现代系统中,在连续内存位置移动元素非常快。使用更复杂的数据结构将很难做得更好。

如果卡的数量可以任意变化,我建议an order statistic tree。在这样的树中,每个节点都跟踪它作为根的子树中的节点数。这可以在任何顺序位置插入和移除。实际上,这为您提供了一个数组,其中插入和删除为 O(log n),并且树是平衡的。

幸运的是,由于您是随机重新插入的,因此如果您最初为卡组创建平衡树,您将“免费”获得预期的 O(log n) 性能。如果您想要最坏的情况 O(log n),您可以使树自平衡(红黑、AVL 等)。

要从牌组顶部发牌,请删除位置 0。要重新插入,请在 0-51 中选择一个随机数,然后插入该序号位置。

【讨论】:

  • 如何插入数组随机位置是 O(1)?我不需要移动位于插入卡前面的其余卡吗?使用数组弹出也非常棘手。 (卡片数量不变)
  • 大O的定义总是与一些描述输入大小的变量有关。如果输入大小不变,那么每个操作都是常数时间。弹出如何棘手?将所有卡片向上移动 1。
  • @Gene 不会是 variable 是数组大小吗?就像对数组进行排序一样。
  • 如果总是有 52 张卡,则数组大小不变。要使大 O 有意义,您需要有一个任意大小的牌组。
  • 你是对的,虽然它是 O(1),但我正在寻找一个具有恒定数组大小的有效解决方案,因为在数组中移动值有点烦人,而且它不是普通扑克卡,所以卡的数量比较大
猜你喜欢
  • 1970-01-01
  • 2011-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-22
  • 2014-12-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多