我有一个Person
个对象的大型数据集,这些对象在列表中排队。我希望数据结构能够有效地执行以下操作。
Person
。Person
。Person
是否存在,如果存在,请将其删除并将其放在队列末尾。Person
。所有这些操作都可以有O(1)时间吗? 到目前为止,我已经提出了两种方法,但它们并不是最优的。
ArrayList<Person>
+ HashMap<Person, Integer>
HashMap
存储Person
个对象的索引。这为操作2和3提供了O(n)时间(删除ArrayList
中的元素)
ArrayDeque<Person>
/ LinkedList<Person>
他们为前2个操作提供O(1),但为最后两个操作提供O(n)。
在我的情况下,空间复杂度不得大于O(n)。操作4的密集度较低,因此我可以容忍一种效率稍低的方法。
任何建议将不胜感激。提前谢谢!
答案 0 :(得分:3)
我认为要求3意味着&#34;通过某个键找到一个人&#34; (例如它的姓氏)?
我有一种强烈的感觉,你不能在O(1)中拥有所有这些要求,甚至没有摊销时间(这样的事情是众所周知的)。但是你可以将它们全部放在O(log N)中。你必须从一个红黑树的实现开始(在C ++中使用std :: map,我相信这是Java中的SortedMap),并修改节点结构以保持其子节点中所有节点的数量。树。这将通过索引为您提供O(log N)访问,以及在树中的任何位置插入和删除O(log N)。通过某个键找到一个人可以通过外部哈希表(红黑树节点)在O(1)中完成。
如果您对O(N)的要求4没有问题,那么我建议在Java中使用像LinkedHashMap这样的东西,它在O(1)中给出了要求1到3,而req。 4可以通过在O(N)中迭代来完成。
答案 1 :(得分:2)
如果问题尚未标记为java
,而是c++
,则std::deque
和std::unordered_map
的组合几乎就足够了。我说几乎是因为第三个请求相当复杂,我不知道如何在O(1)
中结合其他三个请求。
std::unordered_map
在Java中具有等效的HashMap
,但std::deque
提供的内容和ArrayDeque
不提供,O(1)
随机访问 - &gt;您的请求编号四。即使它has already been discussed,ArrayDeque
中仍然缺少此功能,但我认为手动添加它并不困难。毕竟,std::deque
只是一个带有固定大小缓冲区指针的向量。
在任何体面的deque实现中,前两个操作都是O(1)
。根据第3号请求,HashMap
(或std::unordered_map
)会在Person
时间内向您提供特定O(1)
是否存在的信息,您可以将其放在最后同样的复杂性。删除是一个问题,因为必须移动其他元素,并且使用此策略无法在O(1)
中获取。