知识点贪心
描述
有 n 个活动即将举办,每个活动都有开始时间与活动的结束时间,第 i 个活动的开始时间是 starti ,第 i 个活动的结束时间是 endi ,举办某个活动就需要为该活动准备一个活动主持人。
一位活动主持人在同一时间只能参与一个活动。并且活动主持人需要全程参与活动,换句话说,一个主持人参与了第 i 个活动,那么该主持人在 (starti,endi) 这个时间段不能参与其他任何活动。求为了成功举办这 n 个活动,最少需要多少名主持人。
数据范围: ,
复杂度要求:时间复杂度 ,空间复杂度
示例1
输入:
2,[[1,2],[2,3]]
复制返回值:
1
复制说明:
只需要一个主持人就能成功举办这两个活动
示例2
输入:
2,[[1,3],[2,4]]
返回值:
2
说明:
需要两个主持人才能成功举办这两个活动
题解
思路:
- 将输入的数据按照开始时间升序排列,对于第一个开始的节目肯定需要一个主持人
- 对于第K场节目,如果前面的K-1场中存在结束时间小于等于第K场开始时间的则不用增加新的主持人,否则需要新增一个主持人
实现步骤:
- 将输入的数据按照开始时间升序排列
- 使用一个小根堆存放结束时间,并且将小根堆初始化为INT_MAX
- 使用一个计数器记录需要多少主持人
- 遍历排序后的数组
- 如果开始时间小于堆顶时间,将计数器加一,并且将该场的结束时间放入小根堆中
- 如果开始时间大于等于堆顶时间,则表示该主持人可以主持当前场的节目,弹出堆顶元素,并将该场的结束时间放入小根堆中
代码如下:
// https://www.nowcoder.com/practice/76039109dd0b47e994c08d8319faa352?tpId=295&tags=&title=&difficulty=0&judgeStatus=0&rp=0&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E7%25AE%2597%25E6%25B3%2595%25E7%25AF%2587%26topicId%3D295
using namespace std;
int minmumNumberOfHost(int n, vector<vector<int>> &startEnd)
{
if (n <= 0)
{
return n;
}
// 按照节目的结束时间进行排序
std::sort(startEnd.begin(), startEnd.end(), [](const std::vector<int> &left, const std::vector<int> &right)
{
if (left[0] < right[0])
{
return true;
}
if (left[0] > right[0])
{
return false;
}
return left[1] < right[1]; });
std::priority_queue<int, std::vector<int>, std::greater<int>> q;
q.push(INT_MAX);
// 这种思路不太明显,每次将s[1]放入q中,然后q.pop表示的是可以减少一个主持人
// for (auto &s : startEnd)
// {
// if (s[0] >= q.top())
// {
// q.pop();
// }
// q.push(s[1]);
// }
// return q.size() - 1;
// 这个思路比较清晰
// q总是存放当前正在进行的节目的结束时间
// 如果遇到可以复用的主持人,那么弹出堆顶元素,然后将新的结束时间放入堆中,实际上就是更新这个主持人的结束时间
// 再啰说几句:
// 我们从开始时间最小的节目开始遍历,如果需要新的主持人,则放入其结束时间
// 如果不需要新的主持人,那么只需要更新这个主持人的结束时间即可
int counter = 0;
for (auto &s : startEnd)
{
if (s[0] >= q.top())
{
q.pop();
}
else
{
counter++;
}
q.push(s[1]);
}
return counter;
}