【问题标题】:Which data structure to use for the following class以下类使用哪种数据结构
【发布时间】:2019-11-29 21:13:33
【问题描述】:

我已经给出了这两个类(在代码块下面),我必须在不再是 O(log(N) 的时间内实现给定的 TTEvent 方法。我可以使用以下数据结构:

  • Integer[] - 起点或持续时间数组
  • 列出、排队、出列或设置起点或持续时间
  • 地图 - 起点到终点或持续时间的映射
  • 地图 - 起点到时间间隔的映射
  • TTinterval[] - 时间间隔数组
  • 列出、排队、出列或设置时间间隔

其中还有一些持续时间到 xyz 的映射,但由于持续时间不是唯一的,我立即排除了这些。

我可以使用链表、数组列表、哈希图等子类型。

我似乎找不到合适的数据结构来使用。我大部分时间都坚持通过持续时间的方法。我能想到的在这些结构中查找数据的所有方法都会比 O(log(N),主要是 O(N) 慢,因为我会循环或在地图上调用 .contain(value)

假设 N 会大而不是小。

现在我不想要一个解决方案,而是一些关于什么是最需要使用的结构的指针,也许还有一些专门关于通过持续时间的方法的提示。

Java 编译器必须是 1.8,如果这有什么不同的话(jre/jdk 1.8)

    package tp;

    /**
    * Non changeable time-interval. start and end time-points are considered inclusive.
    */
    public class TTInterval {

      private final int start;

      private final int end;

      private final int duration;

      /**
       * Constructor.
       * 
       * @param start startpoint
       * @param end endpoint
       */
      public TTInterval(int start, int end) {
          this.start = start;
          this.end = end;
          this.duration = end - start + 1; // end inklusive
      }

      /**
       * @return startpoint
       */
      public int getStart() {
          return start;
      }

      /**
       * @return endpoint
       */
      public int getEnd() {
          return end;
      }

      /**
       * @return length
       */
      public int getDuration() {
          return duration;
      }

      @Override
      public String toString() {
          return "[(" + start + "-" + end + ")," + "{" + duration + "}]";
      }

      @Override
      public int hashCode() {
          final int prime = 31;
          int result = 1;
          result = prime * result + end;
          result = prime * result + start;
          return result;
      }

      @Override
      public boolean equals(Object obj) {
          if (this == obj) {
              return true;
          }
          if (obj == null) {
              return false;
          }
          if (getClass() != obj.getClass()) {
              return false;
          }
          TTInterval other = (TTInterval) obj;
          if (end != other.end) {
              return false;
          }
          if (start != other.start) {
              return false;
          }
          return true;
      }

    }


import java.util.HashMap;
import java.util.LinkedHashMap;

/**
 * An event consists of a unchangeable name and a collection of time intervals to which it happens.
 * 
 * It delivers information regarding its assigned time intervals.
 * 
 */
public class TTEvent {

    private final String title; 
    private final LinkedHashMap<Integer, TTInterval> intervals; //not sure if this is a good way



    /**
     * constructor.
     * 
     * @param title - name of the event
     */
    TTEvent(String title, String[] attributes) {
        this.title = title;
        this.intervals = new LinkedHashMap<Integer, TTInterval>();
    }


    /**
     * Checks if the provided time-interval (defined by startSlot and endSlot) coincides with any time- 
     *interval already assigned to the event.
     *
     * This method has to work in O(log(N)) (N = number of time intervals).
     * 
     * @param startSlot startpoint (inclusive) of the interval to check
     * @param endSlot endpoint (inclusive) of the interval to check
     * 
     * @return true, if there is a collision, otherwise false
     */
    private boolean conflictingInterval(int startSlot, int endSlot) {
        boolean result = false;
        while ((startSlot <= endSlot) && !result) {
            result = intervals.containsKey(startSlot);
            startSlot++;
        }
        return result;
    }

    /**
     * Adds the given time interval to the event (defined by startSlot and endSlot)
     * 
     * This method has to work in O(log(N)) (N = number of time intervals).
     * 
     * @param startSlot startpoint (inclusive) 
     * @param endSlot endpoint (inclusive) 
     * 
     * @pre endSlot &ge; startSlot
     * @pre startSlot &amp; endSlot &ge; 0
     */
    void addTimeInterval(int startSlot, int endSlot) {
        assert startSlot <= endSlot;
        assert startSlot >= 0;
        assert !conflictingInterval(startSlot, endSlot);

        intervals.put(startSlot, new TTInterval(startSlot, endSlot));
    }

    /**
     * Removes the time interval referenced by the startpoint and returns the removed time interval
     *
     * This method has to work in O(log(N)) (N = number of time intervals).
     * 
     * @param startSlot startpoint
     * @pre startSlot &ge; 0
     * @return the removed time interval, or null, if there was none
     */
    TTInterval removeTimeInterval(int startSlot) {
        assert startSlot >= 0;

        return intervals.remove(startSlot);
    }



    /**
     * If the given time point is used by the event, then the time interval which includes the time point 
     * is returned
     * 
     * This method has to work in O(log(N)) (N = number of time intervals).
     * 
     * @param timeslot the time point to look for
     * @pre timeslot &ge; 0
     * 
     * @return time interval which includes the time point, or null, if there is none
     */
    public TTInterval getIntervalContaining(int timeslot) {
        assert timeslot >= 0;

    }


    /**
     * Returns the (time wise)  first time interval which has the duration to look for.
     * 
     * This method has to work in O(log(N)) (N = number of time intervals).
     * 
     * @param duration - exact duration of the time interval to look for (in time slots)
     * @pre duration &gt; 0
     * 
     * @return First time interval with the specified duration, or null, if there is none
     */
    public TTInterval getfirstIntervalByDuration(int duration) {
        assert duration > 0;
    }


    /**
     * Returns the (time wise) first time interval which is the closest to the min-duration to look for 
     * (so the time interval with the shortest fitting min-duration)  So the duration of the returned 
     * time interval is equal or longer then the min-duration to look for.
     * 
     * This method has to work in O(log(N)) (N = number of time intervals).
     * 
     * @param minDuration exact duration of the time interval to look for (in time slots)
     * @pre minDuration &gt; 0
     * @return First time interval with the desired minduration or longer, or null, if there is none
     */
    public TTInterval getfirstIntervalByMinDuration(int minDuration) {
        assert minDuration > 0;
    }


    @Override
    public String toString() {
    }

}

【问题讨论】:

  • 那么哪些方法需要在 O(log(n)) 内?
  • TTEvent 的所有方法,都有“此方法必须在 O(log(N)) 中工作(N = 时间间隔数)。”在评论中。我从类中排除了所有其他方法,所以它应该是几乎所有方法。

标签: java list dictionary collections set


【解决方案1】:

如果我对您的问题的理解正确,我建议使用 List 作为数据结构,因为它是可扩展的,并且您可以相当容易地获得它的排序表示。另外,我建议您对列表以及我建议使用Binary search 的搜索问题进行排序,因为它的 O(log n)。因此,如果您将元素插入到列表中,请搜索它们各自的位置并使用List.add(index,element)Oracle Doc 将其添加到所述位置。搜索元素也是如此,只是没有添加。

【讨论】:

  • 列表不是超级慢吗?根据我得到的图表, List.add(int, E) 是 O(N) 任何不是列表末尾的地方。删除也一样。
  • 这取决于您使用的是哪个列表,CopyOnWriteArrayList 就像您在大多数需求中非常缓慢一样。然而,LinkedList 在添加和删除元素方面非常快。并且 ArrayList 对于添加和获取元素非常快。我建议您查看this 网站了解更多详细信息,以便您决定何时使用哪个列表。
猜你喜欢
  • 1970-01-01
  • 2017-10-27
  • 2014-08-12
  • 1970-01-01
  • 1970-01-01
  • 2013-07-14
  • 2011-11-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多