Amazon Interview-Design Meeting Scheduler
В последнее время я взял интервью. Мне было предложено создать планировщик встреч, как в календаре Outlook Microsoft, так и в календаре gmail.
Я предложил создать массив из 48 на каждый день. Каждые 30 минут представляют запись массива.
Я должен убедиться, что следующая встреча не столкнется с предыдущей встречей.
Мое решение прекрасно работает, но оно слишком много.
Может кто-нибудь скажет мне, как мне найти лучшее решение для обнаружения столкновения для встреч.
Я не знаю всех встреч в начале. Они будут добавлены случайным образом позже.
Спасибо,
Ответы
Ответ 1
Начните с пустого списка встреч, каждый с start_time
и duration
. Мы будем вести отсортированный список встреч start_time
.
Чтобы добавить собрание в список, найдите, где он принадлежит в списке, выполнив двоичный поиск. Когда вы найдете индекс, выполните две проверки, чтобы избежать столкновения; рассмотрите собрания непосредственно перед и после собрания, которое будет вставлено (если они существуют).
- Утверждение перед встречей
start_time + duration
не превышает новое собрание start_time
.
- Утверждение нового собрания
start_time+duration
не превышает послепродажное start_time
.
Если утверждения выполнены, добавьте собрание в список.
Эта операция добавления занимает время O(log(list_size))
.
Примечание. Этот подход предполагает, что добавление встречи с перекрытием является недопустимой операцией. Если перекрытия разрешены к существованию, вам придется проверить за пределами встреч, непосредственно предшествующих/после нового собрания.
Ответ 2
Мы можем иметь структуру дерева (BST) для хранения запросов (объект запроса: время начала/время окончания/дата/приоритет и т.д.). Таким образом, операции добавления/удаления/поиска/обновления могут быть достигнуты с помощью O (height_of_tree). Если мы используем сбалансированное дерево, мы можем получить оптимизированное время работы. то есть O (log n) для каждой из вышеупомянутых операций.
Этот подход лучше, чем метод отсортированного списка, поскольку список поддерживается массивом фиксированного размера в случае ArrayList, который принимает O (n) для копирования элементов из старого массива в новый массив. Если мы используем связанный список, двоичный поиск невозможен.
Комментарии приветствуются!
Ответ 3
Вот мое решение, которое вставляет с помощью двоичного поиска
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 start time
if (this.startTime.compareTo(o.endTime) > 0) {
return 1;
}////start time is after the other 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");
}
}
}
Ответ 4
в то время как использование сортированного массива и двоичного поиска является эффективным, обратите внимание, что вставка будет принимать o (n), если не будет найдено столкновение, так как массиву необходимо скопировать собрания. Не уверен, что это наиболее оптимальное решение.
Ответ 5
Если отсортированный список является массивом, я полагаю, что операция добавления будет принимать O (n), так как вы должны перенести встречу, которая начинается после встречи с вставкой.