我们可以举行的最大会议次数

时间:2019-06-07 19:38:36

标签: java algorithm

在面试时被要求计算基于给定的两个数组可以举行的最大会议次数。

数组的大小为1到50,并且数组中的值最大为1到1000。

我有一个代表会议开始时间的数组-[1,3,3,5,7]。 另一个代表上述会议所需时间的数组-[2,2,1,2,1]

根据上述数据,第一次会议从1开始,持续2个小时。因此会议时间为2小时,因此从1小时到3小时不等。 第二次和第三次会议从3开始,持续2个小时或1个小时。因此他们在第二次会议上覆盖3到5,在第三次会议上覆盖3到4。 第四次聚会从5点开始,持续2小时。持续时间为2小时,因此覆盖5到7 上次会议从7点开始,持续1小时。

第二个和第三个同时发生,所以我们只需要选择一个就可以安排最大数量的会议。

对于上面给出的示例数据,我们可以安排4次会议。

另一个例子:

会议开始时间-[1,3,5]。 会议花费的时间-[2,2,2]。

这里没有会议可以冲突,因此最多可以安排3次会议。

这是我想出的代码:

public static int getMaximumMeetings(List<Integer> start, List<Integer> timeTaken) {
    // Map with key as meeting start time, and value as the list of time taken values.
    Map<Integer, List<Integer>> map = new LinkedHashMap<>();
    for (int i = 0; i < start.size(); i++) {
        List<Integer> list = map.get(start.get(i));
        if (list == null) {
            list = new ArrayList<>();
        }
        list.add(timeTaken.get(i));
        map.put(start.get(i), list);
    }
    System.out.println(map);

    // Get meetings one by one
    Set<Integer> keys = map.keySet();
    Iterator<Integer> it = keys.iterator();
    Integer time = it.next();
    List<Integer> list = map.get(time);
    // Sort the time taken values so we can pick the least duration meeting
    list.sort(null);
    int count = 1;

    while (it.hasNext()) {
        List<Integer> prevList = list;
        int value = prevList.get(0);
        int prevTime = time;

        time = it.next();
        list = map.get(time);
        list.sort(null);
    // Check if total time taken for this meeting is less than the next meeting starting time.
        if (value + prevTime <= time) {
            count++;
        } else {
            time = prevTime;
            list = prevList;
        }
    }
    return count;
}

此程序仅清除了12个中的5个测试用例,其余所有失败。所有测试用例都是隐藏的。所以我不清楚这段代码有什么问题。

3 个答案:

答案 0 :(得分:4)

它是经典的“间隔调度问题”。您的方法将以最短的时间参加会议。

最短的持续时间无法提供最佳输出。 示例之一可能是间隔(以开始时间为结束时间)

1-11、10-12、13-20、21-30、29-32、31-40

可以证明,最佳解决方案是首先选择最短的完成时间。

使用此算法 按完成时间对元素进行排序。 使用贪婪并包括第一个间隔。标记结束时间。

如果第二个间隔在结束时间之后开始,则也将其包括在内并更新结束时间。否则,请移至第三间隔。

继续该方法。

您将获得会议数量以及会议列表

答案 1 :(得分:1)

我可以想到您没有考虑的以下问题(尽管您的算法思想不正确,这将是主要问题):

  1. 无输入验证:您无需检查输入(此处为列表)的所有值是否都在1到50之间。时间数组中的负值对于结果至关重要。您都不检查两个输入列表的长度是否相同。
  2. 还有其他限制吗?就像面试期有几个小时一样。您对此没有任何检查。
  3. 构建map并进行两个同时开始的采访时,无论时间长短,您总是会进行第一次采访。这样,如果第一次面试要花更多的时间,而第二次面试要花更多的时间。

说句公道话,您可能很难读懂。

答案 2 :(得分:1)

可以使用贪婪方法解决此问题。 @Abhay已经提供了不错的explanation,而我想添加一些代码。

以下是一些基本的实现示例,并附有我的评论。主要思想来自here,其中还包括复杂性分析和正确性证明。

static int getMaximumMeetings(List<Integer> start, List<Integer> timeTaken) {
    List<Interval> list = new ArrayList<>(); // create a List of Interval
    for (int i = 0; i < start.size(); i++) {
        list.add(new Interval(start.get(i), start.get(i) + timeTaken.get(i)));
    }
    list.sort(Comparator.comparingInt(i -> i.end)); // sort by finish times ascending

    int res = 0;
    int prevEnd = Integer.MIN_VALUE; // finish time of the previous meeting

    for (Interval i : list) {
        if (i.start >= prevEnd) { // is there a conflict with the previous meeting?
            res++;
            prevEnd = i.end; // update the previous finish time
        }
    }
    return res;
}

仅是一些Interval实体的示例:

class Interval {
    int start;
    int end;    
    Interval(int start, int end) {
        this.start = start;
        this.end = end;
    }
}