查找运行时为O(1)的最低数目-java

查找运行时为O(1)的最低数目-java,java,algorithm,data-structures,Java,Algorithm,Data Structures,我需要创建一个基于链表、数组和恒定内存使用的数据结构 作为输入,我得到两个数字:N和M N表示键上磁盘的最大容量,M表示计算机硬盘的最大容量,因此M>N 因此,我需要创建一个程序,将信息从硬盘“移动”到键上的磁盘,该程序需要实现以下方法: 插入(数据)-在键上将数据插入磁盘,如果已满,则删除最不重要的数据(*):最坏情况运行时O(1) 删除(数据)-在键-O(1)上从磁盘删除给定数据 (*)用户可以更改文件的重要性 最大内存使用量为O(M) 到目前为止我所做的: 我创建了一个数组[1…M],它将

我需要创建一个基于链表、数组和恒定内存使用的数据结构

作为输入,我得到两个数字:N和M

N表示键上磁盘的最大容量,M表示计算机硬盘的最大容量,因此M>N

因此,我需要创建一个程序,将信息从硬盘“移动”到键上的磁盘,该程序需要实现以下方法:

  • 插入(数据)-在键上将数据插入磁盘,如果已满,则删除最不重要的数据(*):最坏情况运行时O(1)
  • 删除(数据)-在键-O(1)上从磁盘删除给定数据
  • (*)用户可以更改文件的重要性

    最大内存使用量为O(M)

    到目前为止我所做的:

    我创建了一个数组[1…M],它将“保存”计算机数据,我创建了一个双链接列表,它将保存关键数据上的磁盘。[想法是:每次将数据添加到键上的磁盘时,它都会添加到链接列表中,我可以使用数组作为索引(/key)存储直接访问数据。]

    我的计算机数据字段:

    node firstNode;
    node currentNode; 
    node[] dataCollection; // Will hold computer hard-drive data
    
    所以我想创建一个方法,用我想添加的数据替换最不重要的数据[这样我就可以在Insert中使用],我的替换代码:

    public void replace(int leastImportantdata, int insertData){
        node leastImportant = dataCollection[leastImportantdata];
        if (leastImportant.prev!=null) leastImportant.prev.next=dataCollection[insertData-1];
        if (leastImportant.next!=null) leastImportant.next.prev=dataCollection[insertData-1];
        numOfReplacements++;
    
    因此,我的主要问题是在给定这两个“组合”数据结构的情况下找到最不重要的数据,并且仍然保持O(1)的运行时间,特别是当用户决定更改文件的重要性时

    • 假设我们从{4,3,2,1}(数字代表重要性)开始,最不重要的数据是1。突然,用户决定将最后一个文件的重要性更改为5,我们得到{4,3,2,5},最不重要的数据是2

    有什么想法吗?

    为了能够找出最不重要的数据,您需要在列表中添加一个订单

    那么首先考虑的是链表的顺序有什么关系吗?您似乎是基于索引而不是遍历列表来获取数据的。(如果这个顺序很重要的话,我其余的回答可能不会有什么帮助:D)

    这意味着您可以潜在地将项目插入列表中,以便按照最低优先级排序,这将允许您以恒定的性能获取要删除的项目,只要您有对列表标题的引用

    不幸的是,这会增加插入的复杂性。要解决此问题,您可以将优先级映射保留到具有该优先级的链接列表中的最后一个(可能是第一个)文件

    使用此映射,您应该能够立即确定新文件需要插入的位置,从而获得稳定的性能

    因此,如果你有3个文件p(A)=1,p(B)=3,p(C)=3,你的映射看起来像1->(A,A)3->(B,C),如果你想插入另一个优先级为1的文件,它应该在A之后,如果你想插入优先级为2的文件,它应该在B之前

    显然,我在这里假设了有限数量的可能优先级,并且使用的优先级之间没有差距。(这需要搜索)


    希望这有助于解决您的问题,我的建议如下:

    • 定义节点类以实现可比较的接口

    • 以跳过列表的形式实现数据收集—您可以使用


    使用SkipList实现可以确保条目按重要性排序

    根据JavaAPI文档,这个类()实现了SkipList的并发变体,为containsKey、get、put和remove操作及其变体提供了预期的平均日志(n)时间开销

    一般来说,该实现允许项查找的效率与平衡二叉搜索树(即,使用)相当


    最后,了解有关SkipList的更多信息,以及如何编写自己的实现。

    什么是“重要性”范围?也就是说,可以分配给数据的最高和最低重要性是什么?当O(logn)几乎可以肯定是足够的,并且做得比这更好几乎是不可能的时候,为什么您觉得需要O(1)?如果他更加关注他的设计,这些问题可能没有必要。使用SkipList有助于为这个问题提供一个非常简单和干净的解决方案。如果您可以使
    insert
    O(1),那么您就可以按O(N)排序:首先插入N个项目。现在还不需要删除任何内容。然后插入N个值为“无穷大”的项。每次添加“无限”项时,原始项中的一个将被删除-将该项附加到输出中。Tada,你已经做了不可能的事情:基于比较的排序比O(N log N)快。@IGwe:但要求的不是“简单干净的解决方案”,而是O(1)插入和O(1)删除,这是SkipList不能保证的。使用我建议的SkipList实现,不需要有限的优先级范围。@IGwe跳过列表没有恒定的复杂性我需要设计结构,基本上我可以设计“智能”输入管理器。但话说回来,一旦键上的磁盘已满,我需要找到一种指向重要性最低的索引的方法。@采用上述方法的法学家列表的开头将始终具有最低优先级,您可以使用映射插入具有优先级的新项。当您需要更改节点的优先级时,您需要将其从列表中删除并重新插入到正确的位置。所有这些操作都应该具有恒定的复杂性。唯一的问题可能是当优先级为1 10 100时,它们之间有很大的差距。@IGwe你是对的,我需要使用某种动态数据结构。我只是觉得跳过列表不是最好的选择,但您可能只是给了我一个想法:-)它看起来是O(logn)插入/删除的一个很好的解决方案。使用双链表和数组[或任何类型的结构来保存indexex]保存索引更有用