Algorithm 亚马逊访谈-设计会议调度器
最近,我接受了一次采访。我被要求设计一个会议日程安排程序,就像在Microsoft outlook日历或gmail日历中一样。 我建议每天创建48个数组。每30分钟一次,表示数组项 我必须确保下次约会不会与上次会议冲突 我的解决方案工作正常,但它浪费了太多内存 有谁能告诉我如何找到更好的解决方案来检测会议碰撞 一开始我不知道所有的会议。它们将在以后随机添加Algorithm 亚马逊访谈-设计会议调度器,algorithm,Algorithm,最近,我接受了一次采访。我被要求设计一个会议日程安排程序,就像在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