You need to enable JavaScript to run this app. 固定时长区间最大重叠查找:活动出席率最大化算法优化咨询
优惠活动
大模型
产品
解决方案
定价
更多

固定时长区间最大重叠查找:活动出席率最大化算法优化咨询

固定时长活动最优调度高性能实现方案

针对500人规模、1个月时间跨度的调度场景,直接用差分数组+批量统计的方案就能解决,时间复杂度仅为O(N*k + M),远低于你之前实现的O(n³),最坏场景下运行耗时也能控制在毫秒级。

核心思路

你之前踩的两个坑本质都是方法适配错了:

  • O(n³)的滑动窗口是逐次遍历每个时间点、再逐人校验是否冲突,冗余计算太多
  • 参考的单点重叠计数法,本身是算“某一个时间点最多人有空”,但你要的是“某一段固定长度的时间,全程最多人有空”,规则不匹配
    这个方案的核心是把逐人逐窗口校验的冗余操作,替换为差分数组的批量区间计数,完全消除重复计算:
  • 计算规则和需求完全匹配:只要活动的完整时间段落在某参与人的任意空闲区间内,就算该人可以出席
  • 把所有时间转换为固定粒度的数值索引,用差分数组快速统计每个合法起点的可出席人数

具体实现步骤

1. 统一时间粒度与预处理

首先把所有可调度范围、参与人的忙碌/空闲区间,统一转换为从可调度范围起点开始的固定粒度偏移量,比如选1分钟、15分钟为粒度(粒度越粗,计算越快)。
额外补全参与人的空闲区间边界:在可调度范围的起点之前、终点之后补上“全忙”的边界,方便切割出所有符合要求的空闲段。

2. 差分数组批量计数

  • 初始化一个长度等于「所有合法活动起点槽位数」的差分数组,初始值全为0。
  • 遍历每个参与人的所有空闲区间:
    • 如果某段空闲区间的长度小于活动的固定时长,直接跳过
    • 找出这段空闲区间内,所有能放下完整活动的合法起点范围[s_valid, e_valid]
    • 对差分数组做一次区间加操作:diff[s_valid] +=1,diff[e_valid +1] -=1,代表这段范围内的所有活动起点,都能让这个参与人计入出席名单。

3. 前缀和计算找最优解

对差分数组做前缀和计算,每个位置的前缀和值就是“以这个时间为活动起点时,可全程出席的总人数”,遍历找到数值最大的位置,就是最优活动时间。

关键边界细节

  • 所有时间区间统一按左闭右开规则处理,比如[9:00,10:00)代表9点整到10点整忙碌,10点整即刻恢复空闲,避免端点的计数错误。
  • 如果存在多个并列最大出席数的时间点,可以根据业务规则加排序权重(比如优先选工作时间中点、优先选更早的时间)。
  • 粒度选择可以根据业务调整:如果不需要精确到分钟,换成15分钟为粒度可以进一步降低计算量。

参考实现伪代码

# 基础参数配置
ACTIVITY_DURATION = 120 # 活动固定时长,单位:分钟
SCHEDULE_WINDOW_START = 可调度范围最早时间戳
SCHEDULE_WINDOW_END = 可调度范围最晚时间戳
TIME_SLOT_STEP = 1 # 每个时间槽的粒度,单位:分钟

# 计算合法的活动起点总槽位
valid_slot_count = (SCHEDULE_WINDOW_END - SCHEDULE_WINDOW_START) // TIME_SLOT_STEP - ACTIVITY_DURATION // TIME_SLOT_STEP
diff = [0] * (valid_slot_count + 2)

for person in attendee_list:
    # 把个人忙碌区间转换为左闭右开的相对偏移区间
    busy_intervals = 转换忙碌区间到相对槽位
    # 切割得到所有可放下活动长度的空闲区间
    free_intervals = 切割空闲区间(总可调度槽位范围, busy_intervals)
    for free_start, free_end in free_intervals:
        free_len = free_end - free_start
        if free_len < ACTIVITY_DURATION // TIME_SLOT_STEP:
            continue
        # 这个空闲段内的合法活动起点范围
        valid_start_low = free_start
        valid_start_high = free_end - (ACTIVITY_DURATION // TIME_SLOT_STEP)
        diff[valid_start_low] += 1
        diff[valid_start_high + 1] -= 1

# 计算前缀和找最大值
current_attend = 0
max_attend = -1
best_start_slot = 0
for slot in range(valid_slot_count):
    current_attend += diff[slot]
    if current_attend > max_attend:
        max_attend = current_attend
        best_start_slot = slot

best_activity_start = SCHEDULE_WINDOW_START + best_start_slot * TIME_SLOT_STEP

性能验证

按最坏场景计算:

  • 1个月按22个工作日、每天8小时可调度时间计算,总可调度槽位(按1分钟粒度)为10560个
  • 500个参与人,每人平均10个忙碌区间,总区间操作量仅为500*10=5000次
  • 整体运算量不到2万次,内存占用不到100KB,完全不会出现性能瓶颈。

内容的提问来源于stack exchange,提问作者Ryan Baker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.31 07:54:04