解题思路:
1. 贪心的思想,对于第 i 天,如果有若干的会议都可以在这一天开,那么我们肯定是让 endDay 小的会议先在这一天开才会使答案最优,因为 endDay 大的会议可选择的空间是比endDay 小的多的,所以在满足条件的会议需要让endDay 小的先开。所以我们可以通过 endDay 对events进行升序排序.
2. 在一个会议区间[starDay , endDay] ,我们当然要选择最小的天数来开会,如果这一天已经被利用了,我们依次向后延顺,直到endDay,如果到了endDay还没有时间,那么这个会议就要被抛弃。
3. 利用 set 把所有可能开会的天数添加进去 , 在[starDay , endDay] 区间内查找未被使用的一天,找到了就把这一天 erase 掉 ,对于其他区间的查找 ,能够减少 重复无用的查找。
画图帮助理解:
这个思路是 花花酱 的力扣讲解,可以看一下。
代码1:(超出时间限制 , 代码时间复杂度 O(n^2)
class Solution {
public:
static bool cmp(const vector<int>& x ,const vector<int>& y)
{
return x[1] < y[1];
}
int maxEvents(vector<vector<int>>& events)
{
int size = events.size();
sort(events.begin() , events.end() , cmp); //按照endDay从小到大排序
int ans = 0;
char arr[100001] = {0};
for(const auto& e : events)
{
for(int i = e[0] ; i <= e[1] ;++i)
{
if(arr[i] == 0 )
{
arr[i]++;
ans++;
break;
}
}
}
return ans;
}
};
代码2: (优化过后)
class Solution {
public:
static bool cmp(const vector<int>& x ,const vector<int>& y)
{
return x[1] < y[1];
}
int maxEvents(vector<vector<int>>& events)
{
int size = events.size();
sort(events.begin() , events.end() , cmp); //按照endDay从小到大排序
int ans = 0;
int max_d = events[size-1][1]; //找到一个天数范围,节省空间
int min_d = max_d;
for(const auto& e : events)
{
min_d = min(min_d,e[0]);
}
vector<int> days(max_d - min_d + 1); //开辟一个数组,能容纳所有天数
//iota(days.begin() , days.end() , min_d); iota和下面的for是等价的
for(int i = 0 ; i < days.size() ; ++i) //对空间初始化
{
days[i] = i + min_d;
}
set<int> s(days.begin() , days.end()); //把所有可能的天数存在set中
for(const auto& e : events)
{
auto it = s.lower_bound(e[0]); //lower_bound(val): 返回容器中第一个值[大于或等于] val的元素的iterator位置。
if(it == s.end() || *it > e[1]) //e[0] - e[1] 超出范围 或者 未找到
continue;
//找到了,把这个位置删除,防止多次对一个已经被占用位置的查找 优化
s.erase(it);
ans++;
}
return ans;
}
};