Java面试问题:在O(log(n))时间内通过两个字段获取条目

Java面试问题:在O(log(n))时间内通过两个字段获取条目,java,algorithm,concurrency,binary-tree,Java,Algorithm,Concurrency,Binary Tree,我有一个采访任务,想法是用字段存储元素:id,name,updateTime 应该有方法add(Element),getElement(id),getlastUpdateElements() 要求: 代码应该在Java上 应该是线程安全的 所有这些方法的计算复杂度上界应为O(log(n)) 注释 任何元素的更新时间都可以在运行时更改 GetLastUpdateElements-返回最近更新的元素 我的想法 我不能使用CopyOnWriteArrayList,因为如果键是id,则需要O(N

我有一个采访任务,想法是用字段存储元素:
id
name
updateTime

应该有方法
add(Element)
getElement(id)
getlastUpdateElements()

要求:

  • 代码应该在Java上
  • 应该是线程安全的
  • 所有这些方法的计算复杂度上界应为O(log(n))
注释

  • 任何元素的更新时间都可以在运行时更改
  • GetLastUpdateElements-返回最近更新的元素
我的想法

我不能使用
CopyOnWriteArrayList
,因为如果键是
id
,则需要O(N)才能找到最后更新的元素,这违反了要求

为了使O(log(N))的复杂性与
getLastUpdateElements()
相匹配,我可以通过
updateTime
ConcurrentSkipListSet
与comparator一起使用,但在这种情况下,需要O(N)才能按ID获取元素(请注意,在这种情况下
add(element)
是O(log(N)),因为我们知道新创建元素的更新时间)

我可以使用两个树,第一个是通过id使用comparator,第二个是通过
updateTime
使用comparator,但是我应该使所有的访问方法同步使我的程序成为单线程的


我想我很接近了,只需要找到如何使用O(log(N))获取元素,但我的想法已经没有了。

我希望我正确地理解了您的意思

如果需要存储元素,并且“添加”和“获取”时间低至(log(N)),这听起来像是经典的哈希映射(如果搜索时间达到某个阈值,则使用链表哈希和二叉树-我相信是java 8)。 所以在最坏的情况下是log(N)

对于“GetLastUpdated”函数:您可以在执行该函数时将每个更新的元素存储在堆栈中(不是真正的堆栈,只是不断添加到其中的列表)。只需对列表执行二进制搜索。当您到达最后一分钟更新的第一个项目时,只需返回该项目的索引即可

这样,您只需执行二进制搜索(log(N))

当然,这两种数据结构都有一个锁。 如果您真的想在性能方面深入研究,可以实现两个锁:一个用于插入/更新条目,另一个仅用于读取条目。
与“读者-作者问题”类似:

听起来您指的是一些数据结构操作的特定于编程语言的实现。如果是,那是哪种语言?@TimBiegeleisen that javaI不理解
getElement(Element)
。你传递了元素,你想要它回来?(也许看一看?)@ChatterOne同意,这是一个打字错误。它需要通过Id获取元素。我修复了postI在“我的想法”部分中写的关于该解决方案的帖子。在这种情况下,对结构(映射和堆栈)的所有访问都将在同步化块中。实际上,使程序-单线程“同步”并不意味着“单线程”。您误解了什么是多线程,只要您想要线程安全的代码,就需要以某种方式强制执行锁定(当然,若您有相互信息的话)。但是,如果您将锁定(或者如果您真的想要的话,将同步块)限制在最低限度,那么它是线程安全的,并且仍然允许使用同步块