

这里有两种方法做,贪心和排序:
目录
这里其实很容易想到贪心算法,但是要怎么处理呢?很容易想到排序,这里我们对开始时间和结束时间排序。然后我们维护一个东西:
1.当前活动的开始时间
2.上一个最快结束的结束时间或者上一个最快已经结束的时间
这里第二个有点不好理解,我们来具体走一遍处理思路:
设有开始时间start[i]和结束时间end[j],这里两个序列是我们对开始时间和结束时间排序的结果
1.如果start[i]>=end[j],说明上一个活动刚好结束,说明我们可以从上一个活动直接抽出一个主持人,那么我们根本不需要再多加一个主持人,这个时候就直接结束上一个活动看下一个,即j++
2.否则,说明需要增加主持人的数量
代码如下所示:
- class Solution {
- public:
- /**
- * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
- *
- * 计算成功举办活动需要多少名主持人
- * @param n int整型 有n个活动
- * @param startEnd int整型vector<vector<>> startEnd[i][0]用于表示第i个活动的开始时间,startEnd[i][1]表示第i个活动的结束时间
- * @return int整型
- */
- int minmumNumberOfHost(int n, vector<vector<int> >& startEnd) {
- vector<int> start;
- vector<int> end;
- for(int i=0;i<n;++i){
- start.push_back(startEnd[i][0]);
- end.push_back(startEnd[i][1]);
- }
- sort(start.begin(), start.end());
- sort(end.begin(), end.end());
- int res=0;
- int j=0;
- for(int i=0;i<n;++i){
- if(start[i]>=end[j]){
- j++;
- }else{
- res++;
- }
- }
- return res;
- }
- };
这里的时间复杂度是O(nlogn)
用堆排序,本质上还是用了之前的思想,即当前的活动向之前的未结束活动借人,如果借的到,那么人数就不变,如果借不到,那么人数要加一。
具体转化为操作如下所示:
首先对数组排序,按照start时间优先end的从小到大排序
然后我们维护一个最小堆,这个堆维护结束时间,堆顶的含义是一个活动的最早结束时间:
1.如果当前活动时间开始时间大于等于堆顶,那么说明可以向前面借一个主持人,直接将栈顶pop然后再push当前活动的结束时间
2.否则,直接push
这样,最后留下来的节点个数就是主持人的最小数量
实现上由于可能出现负数,所以一开始要pushINT_MIN,来保证增加第一个主持人
- class Solution {
- public:
- /**
- * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
- *
- * 计算成功举办活动需要多少名主持人
- * @param n int整型 有n个活动
- * @param startEnd int整型vector<vector<>> startEnd[i][0]用于表示第i个活动的开始时间,startEnd[i][1]表示第i个活动的结束时间
- * @return int整型
- */
- bool cmp(vector<int> &a, vector<int> &b){
- if(a[0]==a[0]){
- return a[1]<b[1];
- }
- return a[0]<b[0];
- }
- int minmumNumberOfHost(int n, vector<vector<int> >& startEnd) {
- sort(startEnd.begin(), startEnd.end());
- priority_queue<int, vector<int>, greater<int>> q;
- q.push(INT_MIN);
- for(int i=0;i<n;++i){
- if(q.top()<=startEnd[i][0]){
- q.pop();
- }
- q.push(startEnd[i][1]);
- }
- return q.size();
- }
- };