Algorithm 亚马逊访谈-设计会议调度器

Algorithm 亚马逊访谈-设计会议调度器,algorithm,Algorithm,最近,我接受了一次采访。我被要求设计一个会议日程安排程序,就像在Microsoft outlook日历或gmail日历中一样。 我建议每天创建48个数组。每30分钟一次,表示数组项 我必须确保下次约会不会与上次会议冲突 我的解决方案工作正常,但它浪费了太多内存 有谁能告诉我如何找到更好的解决方案来检测会议碰撞 一开始我不知道所有的会议。它们将在以后随机添加 谢谢,以空的会议列表开始,每个会议都有一个开始时间和持续时间。我们将按开始时间维护会议的排序列表 要将会议添加到列表中,请通过执行二进制搜索

最近,我接受了一次采访。我被要求设计一个会议日程安排程序,就像在Microsoft outlook日历或gmail日历中一样。 我建议每天创建48个数组。每30分钟一次,表示数组项

我必须确保下次约会不会与上次会议冲突

我的解决方案工作正常,但它浪费了太多内存

有谁能告诉我如何找到更好的解决方案来检测会议碰撞

一开始我不知道所有的会议。它们将在以后随机添加


谢谢,

以空的会议列表开始,每个会议都有一个
开始时间和
持续时间。我们将按
开始时间
维护会议的排序列表

要将会议添加到列表中,请通过执行二进制搜索来查找该会议在列表中所属的位置。找到索引后,执行两次检查以避免冲突;考虑插入会议之前和之后的会议(如果存在的话)。< /P>
  • 断言前会议的
    开始时间+持续时间
    不超过新会议的
    开始时间
  • 断言新会议的
    开始时间+持续时间
    不超过会后的
    开始时间
  • 如果满足断言,则将会议添加到列表中

    此添加操作需要
    O(日志(列表大小))
    时间


    注意:此方法假定添加具有重叠的会议是无效操作。如果允许存在重叠,则必须在新会议之前/之后的会议之外进行检查。

    虽然使用排序数组和二进制搜索是有效的,但请注意,如果没有发现冲突,插入将需要o(n),因为数组需要滑动会议。不确定这是否是最佳解决方案。

    如果排序列表是一个数组,我相信添加操作将需要O(n),因为您必须移动在待插入会议之后开始的会议。

    这是我使用二进制搜索插入的解决方案

    public class MeetingScheduler {
    
        static class Meeting implements Comparable<Meeting> {
            Date startTime;
            Date endTime;
            int duration;
    
            public static final int MINUTE = 60000;
    
            //duration in minutes
            Meeting(Date startTime, int duration) {
                this.startTime = startTime;
                this.duration = duration;
                this.endTime = new Date(startTime.getTime() + (MINUTE * duration));
    
            }
    
            @Override
            public int compareTo(Meeting o) {
                if (this.endTime.compareTo(o.startTime) < 0) {
                    return -1;
                }//end time is before the other's start time
                if (this.startTime.compareTo(o.endTime) > 0) {
                    return 1;
                }////start time is after the other's end time
                return 0;
            }
    
            @Override
            public String toString() {
                return "meeting {" +
                        "from " + startTime +
                        ", minutes=" + duration +
                        '}';
            }
        }
    
        private List<Meeting> meetings = new ArrayList<Meeting>();
    
        public Meeting bookRoom(Meeting meeting) {
    
            if (meetings.isEmpty()) {
                meetings.add(meeting);
                return null;
            } else {
                int pos = -Collections.binarySearch(meetings, meeting);
                if (pos > 0) {
                    meetings.add(pos-1, meeting);
                    return null;
                } else {
                    return meetings.get(-pos);
                }
            }
        }
    
        public List<Meeting> getMeetings() {
            return meetings;
        }
    
        public static void main(String[] args) {
            MeetingScheduler meetingScheduler = new MeetingScheduler();
    
            Meeting[] meetingsToBook = new Meeting[]{
                    //October 3rd 2014
                    new Meeting(new Date(2014 - 1900, 10 - 1, 3, 15, 00), 15),
                    new Meeting(new Date(2014 - 1900, 10 - 1, 3, 16, 00), 15),
                    new Meeting(new Date(2014 - 1900, 10 - 1, 3, 17, 00), 60),
                    new Meeting(new Date(2014 - 1900, 10 - 1, 3, 18, 00), 15),
                    new Meeting(new Date(2014 - 1900, 10 - 1, 3, 14, 50), 10),
                    new Meeting(new Date(2014 - 1900, 10 - 1, 3, 14, 55), 10)
            };
    
            for (Meeting m : meetingsToBook) {
                Meeting oldMeeting = meetingScheduler.bookRoom(m);
                if (oldMeeting != null) {
                    System.out.println("Could not book room for " + m + " because it collides with " + oldMeeting);
                }
            }
    
            System.out.println("meetings booked: " + meetingScheduler.getMeetings().size());
    
            for (Meeting m : meetingScheduler.getMeetings()) {
                System.out.println(m.startTime + "-> " + m.duration + " mins");
            }
    
        }
    }
    
    公共类会议调度程序{
    静态类会议实现了可比性{
    日期开始时间;
    日期结束时间;
    int持续时间;
    公共静态最终整数分钟=60000;
    //持续时间(分钟)
    会议(日期开始时间,整数持续时间){
    this.startTime=startTime;
    这个。持续时间=持续时间;
    this.endTime=新日期(startTime.getTime()+(分钟*持续时间));
    }
    @凌驾
    公共内部比较(会议o){
    如果(此.endTime.compareTo(o.startTime)<0){
    返回-1;
    }//结束时间早于对方的开始时间
    如果(此.startTime.compareTo(o.endTime)>0){
    返回1;
    }////开始时间在对方的结束时间之后
    返回0;
    }
    @凌驾
    公共字符串toString(){
    返回“会议{”+
    “from”+startTime+
    “,分钟=”+持续时间+
    '}';
    }
    }
    私人列表会议=新建ArrayList();
    公众会议室(会议室){
    if(meetings.isEmpty()){
    会议。添加(会议);
    返回null;
    }否则{
    int pos=-Collections.binarySearch(会议,会议);
    如果(位置>0){
    会议。添加(pos-1,会议);
    返回null;
    }否则{
    返回会议。获取(-pos);
    }
    }
    }
    公开会议名单(){
    返回会议;
    }
    公共静态void main(字符串[]args){
    MeetingScheduler MeetingScheduler=新建MeetingScheduler();
    会议[]会议Stobook=新会议[]{
    //2014年10月3日
    新的会议(新的日期(2014-1900,10-1,3,15,00),15),
    新会议(新日期(2014-1900、10-1、3、16、00)、15),
    新会议(新日期(2014-1900,10-1,3,17,00),60),
    新的会议(新的日期(2014-1900,10-1,3,18,00),15),
    新会议(新日期(2014-1900、10-1、3、14、50)、10),
    新会议(新日期(2014-1900、10-1、3、14、55)、10)
    };
    用于(会议m:会议记录){
    会议oldMeeting=meetingScheduler.bookRoom(m);
    if(oldMeeting!=null){
    System.out.println(“无法为“+m+”预订空间,因为它与“+oldMeeting”冲突);
    }
    }
    System.out.println(“预订的会议:+meetingScheduler.getMeetings().size());
    对于(会议m:meetingScheduler.getMeetings()){
    系统输出打印长度(m.startTime+“->”+m.duration+“min”);
    }
    }
    }
    
    我们可以使用树结构(BST)来存储请求(请求对象:开始时间/结束时间/日期/优先级等)。这样,添加/删除/搜索/更新操作可以通过O(树的高度)实现。如果我们使用平衡树,我们可以得到优化的运行时间。i、 e.O(对数n)用于上述每个操作

    这种方法优于排序列表方法,因为在ArrayList的情况下,列表由一个固定大小的数组支持,ArrayList需要O(n)将元素从旧数组复制到新数组。如果我们使用linkedlist,二进制搜索是不可能的


    欢迎评论

    我想我忘记提了。一开始我没有访问所有会议的权限。我已经根据您的编辑修改了我的答案。谢谢。。。很酷的方法。类似于B+树的东西::)添加已排序的列表将花费O(列表大小)时间。我遗漏了什么吗?@damned使用二进制搜索,添加操作可以在
    O(log(list_size))
    时间内执行。请参阅:它不包括重复出现的sc