在数据结构

时间:2017-08-01 10:09:17

标签: java algorithm sorting data-structures

我有一个存储大量任务的系统。每个任务都有以下参数:

Time t       
Priority p      

每项任务都有一个独特的时间。这意味着没有2个任务可以具有相同的时间参数 但是,优先级并不是唯一的。多个任务可以具有相同的优先级。

我需要设计一个可以解决四种类型查询的系统。每种类型的查询的概率同样可能。以下是查询类型:

  1. UpdateTask(T,P)
    此查询希望系统将任务的优先级设置为t到优先级p。如果系统中不存在该任务,则会创建一个新任务。如果任务存在,则更新其优先级。

  2. DeleteTask活动(t)的
    此查询希望系统删除与时间t关联的任务。如果系统中不存在此类任务,则无需采取任何措施。

  3. GetMaximumPriority()和GetMinimumPriority()
    此查询要求系统打印系统中可用任务的最低优先级和最高优先级。

  4. GetPriorityofTaskAtMaximumTime()
    此查询希望系统打印具有参数t(时间)的最大值的任务的优先级

  5. 我需要为这个系统设计数据结构,并为这些数据结构实现算法。我需要在Java中实现它。

    我的方法:创建一个HashMap,其中Key为Time,Value为Priority。 HashMap允许我在固定时间内解决前两个查询。但最后两个查询的时间复杂度为O(n)

    问题:针对此问题,是否有更好的时间高效且节省空间的数据结构和算法?我主要需要一种方法来解决这个问题。完全实现的代码不是必需的。谢谢。

3 个答案:

答案 0 :(得分:3)

一种可能的方法是维护两个索引:一个用于时间,一个用于优先级。让我们采用两个平衡的搜索树,并进行恒定的时间firstKey() / lastKey()操作。我将使用TreeMap的接口,但它应该具有类似于c ++的std::map的实现(它只是在更新期间维护迭代器到第一个和最后一个元素)。

第一张地图为Map<Time, Priority> tasks,第二张为Map<Priority, Integer> priorities。每个现有优先级值的第二个映射存储具有此优先级值的任务数。因此,您可以将tasks用于第四个查询,将priorities用于第三个查询。

  1. UpdateTask(t,p)

    Priority oldp = tasks.put(t, p);
    if (oldp != null) {
        decreasePriority(oldp);     
    } 
    increasePriority(p);
    

    复杂性: O(log(n))

  2. <强> DeleteTask活动(t)的

    if (tasks.containsKey(t)) {
        Priority oldp = tasks.get(t);
        tasks.remove(t);
        decreasePriority(oldp); 
    }
    

    复杂性: O(log(n))

  3. GetMaximumPriority(),GetMinimumPriority()

    return priorities.lastKey();
    
    return priorities.firstKey();     
    

    复杂性: O(1)(正确lastKey() / firstKey()实施,O(log(n)) java.util.TreeMap。)

  4. <强> GetPriorityofTaskAtMaximumTime()

    return tasks.lastEntry().getValue();
    

    复杂性: O(1)(正确lastEntry()实施,O(log(n)) java.util.TreeMap

  5.     void increasePriority(p) {
            if (priorities.hasKey(p)) { 
                priorities.put(p, priorities.get(p) + 1);
            } else {
                priorities.put(p, 1); 
            }    
        }
    
        void decreasePriority(p) {
            int count = priorities.get(p);
            if (count > 1) {  
                priorities.put(p, count - 1);
            } else {
                priorities.remove(p);
            }   
        }
    

    因此,您将避免操作中的线性复杂性。

答案 1 :(得分:1)

一般approcah - 可能会根据您的数据类型进行更改,我认为您可以使用一种类型的地图数据类型作为关键时间和优先级。每当您想要删除数据时,使用时间作为键和删除来搜索该地图,同样您可以使用时间作为键进行更新。

然后,您可以根据时间和优先级分别列出一个列表,然后根据需要对列表进行排序。

答案 2 :(得分:0)

您可以尝试使用Heap或PriorityQueue,它可以按照here的规定在O(1)中找到最小值和最大值。
他们还删除并提取O(log n)中的min和max,但搜索将保持在O(n)。 您可能必须为Task类实现Comparator ...