设计用于合并会议日程的数据结构

时间:2011-12-01 18:52:00

标签: data-structures

我被要求为会议日程设计一个数据结构,然后合并它们。例如,如果人A从上午9:00到上午10:00开会,而人B在上午9:30到11:30开会,那么合并的忙时段是从上午9:00到11:30。

我为Person创建了类,这个类有会议对象的集合。 Meeting类具有24小时格式的开始时间[hh:mm],因此我可以轻松地进行比较。

class Person {
String name;
Collection<Meeting> meetings;

}


class Meeting{
int hh, mm;
int duration; // duration will be in minutes from where we can get the end time. 
}

我想知道哪种数据结构对合并最有效。 一种方法是使用已排序的会议ArrayList。

任何更好的设计都值得赞赏。

4 个答案:

答案 0 :(得分:2)

由于安排时间少于15分钟的会议是不现实的,我会满足于... long。每天64位,足够16小时;我不需要那么多。或者,如果你愿意,可以使用两个长/三个整数。

然后合并是一个|操作。对于较大的时隙,我可以移位 - 或者它们,然后检查未设置的位作为会议开始时间。这种高度压缩的数据结构只会因为低级操作而对任何索引产生影响。 CPU缓存可以适应数百天/用户的日程安排。

答案 1 :(得分:2)

由于@Anonymouse建议您可以使用96位,即12个字节来表示一天,因此从凌晨1点开始的30分钟会议将表示为110000,您可以使用简单的|对所有数字进行操作。

时间O(n)存储器O(12n)字节。理论上它会更快。


举行会议[分钟开始时间,分钟结束时间]。

重叠时将两个会议(Sa&amp; Sb)合并为Sc

Sc [minimum(SA-start,SB-start),maximum(SA-end,SB-end)]并将合并会议存储在集合中。如果没有重叠,那么您可以单独存储它们。

我们知道一天中的总分钟数= 24 * 60 = 1440 如果你有15分钟单位,那么它变成24 * 60/15 = 96(1字节以下)

因此,每个调度需要2个字节,即字节开始,结束。

时间O(n)存储器O(2n)字节


如果您以后必须删除会议,则这两种方法都不起作用。为此,您肯定会分别保留所有原始会议日程。

答案 2 :(得分:0)

在不合并时间表的情况下计算空闲时间:

  • 员工1的可用性(范围):[9:00至20:00]
  • 员工1的繁忙计划时间间隔: [[9:00,10:30],[12:00,13:00],[16:00,18:00]]
  • 员工2的可用性(范围):[10:00至18:30]
  • 员工2的繁忙计划时间间隔:[[10:00,11:30],[12:30, 14:30],[14:30,15:00],[16:00,17:00]]
  • 自由时间间隔:[[11:30,12:00],[15:00,16:00],[18:00,18:30]]
  • 程序输出:[11h:30m-12h:00m] [15h:00m-16h:00m] [18h:00m-18h:30m]

这是我的方法:我不合并日历以计算空闲时间,而是使用TreeMap将繁忙的日程表标记为“ B”,将空闲时间标记为“ F”。我会在上下限内考虑每一分钟。最初,假设空闲时间可用于下限到上限,地图将更新为“ F”。稍后,地图将根据繁忙的时间表进行更新。因为间隔是一个列表,所以时间复杂度为O(n * 2),每个间隔都需要处理以更新地图。空间复杂度为O(n)。

ScheduleFinderTest test = new ScheduleFinderTest();
test.findFreeSchedules();

public class ScheduleFinderTest {

public void findFreeSchedules() {

    // Employee availability time ( 9:00 to 12:00 )
    MeetingIntervals bound = new MeetingIntervals(9, 00, 20, 00);
    MeetingIntervals busyInterval1 = new MeetingIntervals(9, 00, 10, 30);
    MeetingIntervals busyInterval2 = new MeetingIntervals(12, 00, 13, 00);
    MeetingIntervals busyInterval3 = new MeetingIntervals(16, 00, 18, 00);
    List<MeetingIntervals> allBusyIntervals1 = Arrays.asList(busyInterval1, busyInterval2, busyInterval3);      
    Employee e1 = new Employee("John", bound, allBusyIntervals1);

    // Employee availability time ( 10:00 to 18:30 )
    bound = new MeetingIntervals(10, 00, 18, 30); 
    busyInterval1 = new MeetingIntervals(10, 00, 11, 30);
    busyInterval2 = new MeetingIntervals(12, 30, 14, 30);
    busyInterval3 = new MeetingIntervals(14, 30, 15, 00);
    MeetingIntervals busyInterval4 = new MeetingIntervals(16, 00, 17, 00);
    List<MeetingIntervals> allBusyIntervals2 = Arrays.asList(busyInterval1, busyInterval2, busyInterval3, busyInterval4);
    Employee e2 = new Employee("Christiana", bound, allBusyIntervals2);

    ScheduleFinder scheduleFinder = new ScheduleFinder(Arrays.asList(e1, e2));
    scheduleFinder.find();
   } 
}

@Data
@AllArgsConstructor
class Employee {
   private String name; 
   private MeetingIntervals bounds;
   private List<MeetingIntervals> intervals;    
 }

@Data
@AllArgsConstructor
class MeetingIntervals {
   private int fromHour;
   private int fromMinutes;
   private int toHour;
   private int toMinutes;
 }

public class ScheduleFinder {

private List<Employee> employees;

public ScheduleFinder(List<Employee> employees) {
    this.employees = employees;
}

public void find() {

    // sort all bound hours (from availability)  and get the maximum one
    Collections.sort(employees, (e1, e2) -> e2.getBounds().getFromHour() - e1.getBounds().getFromHour());
    int inTimeHour = employees.get(0).getBounds().getFromHour();
    int inTimeMinutes = employees.get(0).getBounds().getFromMinutes();

    // sort all bound hours ( to availability ) and get the minimum one
    Collections.sort(employees, (e1, e2)-> e1.getBounds().getToHour() - e2.getBounds().getToHour());
    int exitTimeHour = employees.get(0).getBounds().getToHour();
    int exitTimeMinutes = employees.get(0).getBounds().getToMinutes();

    // initially mark the map with free time for bounds as calculated above
    MeetingIntervals availableInterval = new MeetingIntervals(inTimeHour, inTimeMinutes, exitTimeHour, exitTimeMinutes);        
    Map<String, Character> scheduleMap = new TreeMap<>();
    updateSchedule(availableInterval, scheduleMap, 'F');
    System.out.println(scheduleMap);

    // update the map with busy intervals
    List<MeetingIntervals> allBusyIntervals = employees.stream()
            .flatMap(m -> m.getIntervals().stream())
            .collect(Collectors.toList());      
    Collections.sort(allBusyIntervals, (e1, e2) -> e1.getFromHour() - e2.getFromHour());        
    updateScheduleMap(allBusyIntervals, scheduleMap, 'B');
    System.out.println(scheduleMap);

    // print free schedules
    printFreeSchedules(scheduleMap, exitTimeHour, exitTimeMinutes);                     
}

private void updateScheduleMap(List<MeetingIntervals> busyIntervals, Map<String, Character> scheduleMap, char marker) {

    for (MeetingIntervals interval : busyIntervals) {
        updateSchedule(interval, scheduleMap, marker);
    }
}

private void updateSchedule(MeetingIntervals interval, Map<String, Character> map, char marker) {

    int startTimeHour = interval.getFromHour();
    int startTimeMinutes = interval.getFromMinutes();

    int startTimeInMinutes = getTimeInMinutes( startTimeHour, startTimeMinutes); 
    int endTimeInMinutes = getTimeInMinutes( interval.getToHour(), interval.getToMinutes());        

    for (int i = 0; i < (endTimeInMinutes - startTimeInMinutes); i++) {

        String key = getFormattedKey(startTimeHour, startTimeMinutes);

        if (marker == 'B' && map.get(key) != null) {
            map.put(key, marker);               
        } else if (marker == 'F' && map.get(key) == null) {
            map.put(key, marker);
        }

        ++startTimeMinutes;

        if (startTimeMinutes == 60) {
            startTimeMinutes = 0;
            ++startTimeHour;
        }
    }       
}

private int getTimeInMinutes(int hour, int minutes) {
    return ( hour * 60 ) + minutes ;    
}

public String getFormattedKey(int hour, int minutes) {

    StringBuilder sb = new StringBuilder();
    String hourStr = hour + "";
    String minutesStr = minutes + "";

    if (String.valueOf(hour).length() == 1) {
        hourStr = "0" + hour;       
    }

    if (String.valueOf(minutes).length() == 1) {
        minutesStr = "0" + minutes;
    }   

    sb.append(hourStr).append("h:").append(minutesStr).append("m");
    return sb.toString();
}

private void printFreeSchedules(Map<String, Character> scheduleMap, int exitTimeHour, int exitTimeMinutes) {
    boolean intervalStarted = false;
    boolean intervalEnded = false;

    for(String k : scheduleMap.keySet()) {

        if ( scheduleMap.get(k) == 'F' && intervalStarted == false) {
            System.out.print("[" + k);
            intervalStarted = true;
            intervalEnded = false;
        }

        if ( scheduleMap.get(k) == 'B' && intervalStarted == true && intervalEnded == false) {
            System.out.println(" - " + k + "]");
            intervalEnded = true;
            intervalStarted = false;
        }
    }

    if ( intervalStarted == true && intervalEnded == false ) {
        System.out.println(" - " + exitTimeHour + "h:" + exitTimeMinutes + "m]");
      }
    }       
 }

答案 3 :(得分:-1)

这是Task Scheduling的经典问题。