求出所有人的共同空闲时间(一个比较简单的小算法)

316 阅读1分钟

背景

有个需求,是查看所有人日程的功能,需要在界面上显示出所有人的共同空闲时间,这样就可以针对这个空闲时间段申请会议室,而不用一个个去找对应人的空闲时间了。

大致逻辑

将所有人的忙碌时间放进一个集合中进行有序排序,根据一个阶段的忙碌时间统计出一个阶段的空闲时间,然后过滤掉有相交的忙碌时间段,再按之前规则进行遍历过滤,直到没有忙碌时间。

代码

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);
}