​BM96 主持人调度(二)​

知识点​贪心​

描述

有 n 个活动即将举办,每个活动都有开始时间与活动的结束时间,第 i 个活动的开始时间是 starti ,第 i 个活动的结束时间是 endi ,举办某个活动就需要为该活动准备一个活动主持人。


一位活动主持人在同一时间只能参与一个活动。并且活动主持人需要全程参与活动,换句话说,一个主持人参与了第 i 个活动,那么该主持人在 (starti,endi) 这个时间段不能参与其他任何活动。求为了成功举办这 n 个活动,最少需要多少名主持人。


数据范围: [典型-贪心]BM96 主持人调度(二)-中等_贪心算法 , [典型-贪心]BM96 主持人调度(二)-中等_小根堆_02


复杂度要求:时间复杂度 [典型-贪心]BM96 主持人调度(二)-中等_贪心算法_03 ,空间复杂度 [典型-贪心]BM96 主持人调度(二)-中等_贪心算法_04

示例1

输入:

2,[[1,2],[2,3]]

复制返回值:

1

复制说明:

只需要一个主持人就能成功举办这两个活动

示例2

输入:

2,[[1,3],[2,4]]

返回值:

2

说明:

需要两个主持人才能成功举办这两个活动

题解

思路:

  1. 将输入的数据按照开始时间升序排列,对于第一个开始的节目肯定需要一个主持人
  2. 对于第K场节目,如果前面的K-1场中存在结束时间小于等于第K场开始时间的则不用增加新的主持人,否则需要新增一个主持人

实现步骤:

  1. 将输入的数据按照开始时间升序排列
  2. 使用一个小根堆存放结束时间,并且将小根堆初始化为INT_MAX
  3. 使用一个计数器记录需要多少主持人
  4. 遍历排序后的数组
  1. 如果开始时间小于堆顶时间,将计数器加一,并且将该场的结束时间放入小根堆中
  2. 如果开始时间大于等于堆顶时间,则表示该主持人可以主持当前场的节目,弹出堆顶元素,并将该场的结束时间放入小根堆中


代码如下:

// 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

#include <bits/stdc++.h>

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