← 返回博客列表
Bloomberg

Bloomberg 面试题:日程表 Busy View 合并重叠时间段

2025-12-15

题目描述

给定一天中的日程事件列表,实现算法返回 Busy View 时间段列表。Busy View 是将所有重叠或相邻的事件时间段合并后的结果,不显示具体事件详情。

每个事件有开始时间、结束时间和标题。时间精确到分钟。

示例

输入事件列表:
(100, 300, "Some Event")  // 1:00 am 到 3:00 am
(115, 145, "Some Event")
(145, 215, "Some Event")
(200, 400, "Some Event")
(215, 230, "Some Event")
(215, 415, "Some Event")
(600, 700, "Some Event")
(500, 600, "Some Event")

输出 Busy View:
(100, 415)  // 1:00 am 到 4:15 am 忙碌
(500, 700)  // 5:00 am 到 7:00 am 忙碌

解题思路

这是经典的区间合并问题:

  1. 按开始时间对所有事件排序
  2. 遍历事件,如果当前事件与上一个合并后的区间重叠或相邻,则合并
  3. 否则开始一个新的区间

Python 实现

def get_busy_view(events: list) -> list:
    if not events:
        return []
    
    # 按开始时间排序
    events.sort(key=lambda x: x[0])
    
    result = []
    current_start, current_end = events[0][0], events[0][1]
    
    for start, end, _ in events[1:]:
        if start <= current_end:
            # 重叠或相邻,扩展当前区间
            current_end = max(current_end, end)
        else:
            # 不重叠,保存当前区间,开始新区间
            result.append((current_start, current_end))
            current_start, current_end = start, end
    
    # 别忘了最后一个区间
    result.append((current_start, current_end))
    
    return result

# 测试
events = [
    (100, 300, "Event1"),
    (115, 145, "Event2"),
    (145, 215, "Event3"),
    (200, 400, "Event4"),
    (215, 230, "Event5"),
    (215, 415, "Event6"),
    (600, 700, "Event7"),
    (500, 600, "Event8"),
]

print(get_busy_view(events))
# 输出: [(100, 415), (500, 700)]

复杂度分析

进阶:支持多个日历

如果需要合并多个人的日历:

def get_combined_busy_view(calendars: list) -> list:
    # 合并所有事件
    all_events = []
    for calendar in calendars:
        all_events.extend(calendar)
    
    return get_busy_view(all_events)

进阶:找出空闲时间段

def get_free_slots(events: list, day_start: int, day_end: int) -> list:
    busy = get_busy_view(events)
    free = []
    
    current = day_start
    for start, end in busy:
        if current < start:
            free.append((current, start))
        current = max(current, end)
    
    if current < day_end:
        free.append((current, day_end))
    
    return free

# 找出 0:00 到 24:00 之间的空闲时段
print(get_free_slots(events, 0, 2400))
# 输出: [(0, 100), (415, 500), (700, 2400)]

面试要点

  1. 边界情况:空列表、只有一个事件、完全不重叠的事件
  2. 相邻处理:确认 (100, 200) 和 (200, 300) 是否需要合并
  3. 时间格式:确认时间是分钟数还是 HH:MM 格式

需要面试辅助服务?联系我们

需要面试真题? 立刻联系微信 Coding0201,获得真题