LeetCode1353. 最多可以参加的会议数目

力扣

 

         

        

解题思路:

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值