Medium
题目描述
给你一个正整数 days,表示员工可以工作的总天数(从第 1 天开始)。同时给你一个大小为 n 的二维数组 meetings,其中 meetings[i] = [start_i, end_i] 表示第 i 个会议的开始和结束天数(包含边界)。
返回员工可以工作但没有安排会议的天数。
注意: 会议可能会重叠。
示例 1:
输入:days = 10, meetings = [[5,7],[1,3],[9,10]]
输出:2
解释:第 4 天和第 8 天没有安排会议。
示例 2:
输入:days = 5, meetings = [[2,4],[1,3]]
输出:1
解释:第 5 天没有安排会议。
示例 3:
输入:days = 6, meetings = [[1,6]]
输出:0
解释:所有工作日都安排了会议。
约束条件:
1 <= days <= 10^91 <= meetings.length <= 10^5meetings[i].length == 21 <= meetings[i][0] <= meetings[i][1] <= days
解题思路
这道题的核心思路是区间合并问题。我们需要找到所有没有被会议覆盖的天数。
解题步骤:
- 排序:首先按照会议开始时间对所有会议进行排序
- 合并重叠区间:遍历排序后的会议,将重叠的会议区间合并成一个大区间
- 计算空闲天数:统计合并后区间之间的空隙天数,以及开头和结尾的空闲天数
具体实现:
- 排序后,依次检查相邻会议是否重叠(当前会议开始时间 ≤ 上一个会议结束时间)
- 如果重叠,则合并区间(更新结束时间为两者最大值)
- 如果不重叠,则计算空隙天数并开始新区间
- 最后别忘记计算最后一个会议结束后到总天数结束的空闲天数
这种方法的时间复杂度主要由排序决定,为 O(n log n),空间复杂度为 O(1)(不考虑排序额外空间)。
代码实现
class Solution {
public:
int countDays(int days, vector<vector<int>>& meetings) {
sort(meetings.begin(), meetings.end());
int freeDays = 0;
int lastEnd = 0;
for (auto& meeting : meetings) {
int start = meeting[0];
int end = meeting[1];
if (start > lastEnd + 1) {
freeDays += start - lastEnd - 1;
}
lastEnd = max(lastEnd, end);
}
// 最后一个会议结束后的空闲天数
if (lastEnd < days) {
freeDays += days - lastEnd;
}
return freeDays;
}
};
class Solution:
def countDays(self, days: int, meetings: List[List[int]]) -> int:
meetings.sort()
free_days = 0
last_end = 0
for start, end in meetings:
if start > last_end + 1:
free_days += start - last_end - 1
last_end = max(last_end, end)
# 最后一个会议结束后的空闲天数
if last_end < days:
free_days += days - last_end
return free_days
public class Solution {
public int CountDays(int days, int[][] meetings) {
Array.Sort(meetings, (a, b) => a[0].CompareTo(b[0]));
int freeDays = 0;
int lastEnd = 0;
foreach (var meeting in meetings) {
int start = meeting[0];
int end = meeting[1];
if (start > lastEnd + 1) {
freeDays += start - lastEnd - 1;
}
lastEnd = Math.Max(lastEnd, end);
}
// 最后一个会议结束后的空闲天数
if (lastEnd < days) {
freeDays += days - lastEnd;
}
return freeDays;
}
}
var countDays = function(days, meetings) {
meetings.sort((a, b) => a[0] - b[0]);
let freeDays = 0;
let lastEnd = 0;
for (const [start, end] of meetings) {
if (start > lastEnd + 1) {
freeDays += start - lastEnd - 1;
}
lastEnd = Math.max(lastEnd, end);
}
// 最后一个会议结束后的空闲天数
if (lastEnd < days) {
freeDays += days - lastEnd;
}
return freeDays;
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(n log n) | 主要开销在排序,其中 n 是会议数量 |
| 空间复杂度 | O(1) | 只使用常量额外空间(不考虑排序空间) |
相关题目
- . Merge Intervals (Medium)