C#如何不使用大量IF语句计算预约列表中的空闲时间段数量
你当前的实现逻辑完全不符合需求,你现在统计的是「结束时间大于开始时间的有效预约数量」,和空闲时段统计没有关联。
最优实现思路(无大量冗余IF)
核心逻辑靠排序+一次遍历完成,仅保留必要的边界判断,没有多余分支:
- 先将所有时间统一转换为分钟数值(比如8:00转为480,17:00转为1020),避免时间格式比较的复杂逻辑
- 对预约列表按开始时间升序排序,同时合并重叠/相邻的预约,直接过滤无效预约(结束时间<=开始时间的预约)
- 遍历排序合并后的预约列表,依次计算前后两个时间节点的间隙,再加上首尾的工作时段边界间隙,即可得到空闲总数
具体C#实现代码
public int Count(Appointment[] appointments) { // 定义工作时段,转换为0点开始的分钟数简化计算 const int workStart = 8 * 60; const int workEnd = 17 * 60; // 过滤无效预约+格式转换+按开始时间排序 var validAppointments = appointments .Where(a => a.End > a.Start) .Select(a => new { Start = ToMinutes(a.Start), End = ToMinutes(a.End) }) .OrderBy(a => a.Start) .ToList(); // 合并重叠/相邻的预约 var mergedSlots = new List<(int Start, int End)>(); foreach (var appt in validAppointments) { if (mergedSlots.Count == 0) { mergedSlots.Add((appt.Start, appt.End)); continue; } var lastSlot = mergedSlots.Last(); if (appt.Start <= lastSlot.End) { // 重叠则合并,取最晚的结束时间 mergedSlots[^1] = (lastSlot.Start, Math.Max(lastSlot.End, appt.End)); } else { mergedSlots.Add((appt.Start, appt.End)); } } int freeCount = 0; int prevEndTime = workStart; foreach (var slot in mergedSlots) { if (slot.Start > prevEndTime) { freeCount++; } prevEndTime = Math.Max(prevEndTime, slot.End); } // 统计最后一段下班前的空闲 if (workEnd > prevEndTime) { freeCount++; } return freeCount; } // 辅助方法:将Appointment的时间字段转换为分钟数,可根据你实际的时间类型调整实现 private int ToMinutes(DateTime time) { return time.Hour * 60 + time.Minute; }
逻辑验证
用你给出的示例输入测试:
预约列表转分钟后为[570-600, 720-780, 915-990],无重叠无需合并
遍历计算间隙:
- 上班时间480到第一个预约开始570:存在间隙,计数+1
- 第一个预约结束600到第二个预约开始720:存在间隙,计数+1
- 第二个预约结束780到第三个预约开始915:存在间隙,计数+1
- 第三个预约结束990到下班时间1020:存在间隙,计数+1
最终返回4,完全符合预期结果。
内容的提问来源于stack exchange,提问作者maate
相关产品推荐
相关产品推荐

