背景
有个需求,是查看所有人日程的功能,需要在界面上显示出所有人的共同空闲时间,这样就可以针对这个空闲时间段申请会议室,而不用一个个去找对应人的空闲时间了。
大致逻辑
将所有人的忙碌时间放进一个集合中进行有序排序,根据一个阶段的忙碌时间统计出一个阶段的空闲时间,然后过滤掉有相交的忙碌时间段,再按之前规则进行遍历过滤,直到没有忙碌时间。
代码
struct TimeRange
{
int start = 0;
int end = 0;
TimeRange(int start, int end)
: start(start),
end(end)
{
}
};
std::vector<TimeRange> GetFreeTime(const std::vector<TimeRange> & busyTimes)
{
// 总时间: 9 => 18
int start = 9;
int end = 18;
std::vector<TimeRange> result;
// 如果都没忙碌时间,则空闲时间就是从早到晚
if (busyTimes.empty()) {
result.emplace_back(9, 18);
return result;
}
std::vector<TimeRange> items = busyTimes;
while (true) {
// 如果没有忙碌时间,则直接退出循环,返回结果
if (items.empty()) {
break;
}
// 将所有人的忙碌起始时间从低到高排序
std::sort(items.begin(), items.end(), [](const TimeRange & left, const TimeRange & right) {
return left.start < right.start;
});
const auto cur = items[0];
// 取总数中第一个人的忙碌时间和总开始时间进行比较
// 如果比总开始时间大,空闲时间则是总开始时间到第一个忙碌时间
if (start < cur.start) {
result.emplace_back(start, cur.start);
}
// 过滤所有忙碌时间
// 将所有人的时间与当前人的忙碌时间进行比较,过滤出不是当前这个时间段的忙碌时间
// 因为这个忙碌时间段已经不可能是共同空闲时间了
for (auto it = items.begin(); it != items.end();) {
if (it->start < cur.end && it->end <= cur.end) {
it = items.erase(it);
}
else {
++it;
}
}
// 将总开始时间设置成当前这个人的忙碌结束时间
start = cur.end;
}
// 如果忙碌时间不是总结束时间,则说明,这段时间也是共同空闲时间
if (start < end) {
result.emplace_back(start, end);
}
return result;
}
int main()
{
std::vector<TimeRange> busyTimes;
busyTimes.emplace_back(14, 15);
busyTimes.emplace_back(14, 16);
busyTimes.emplace_back(10, 11);
busyTimes.emplace_back(10, 12);
const auto result = GetFreeTime(busyTimes);
}