Leetcode 253 Meeting Room II

该博客介绍了LeetCode第253题的解决方案,旨在找到安排会议所需的最少会议室数量。提供了两种解法:一是利用最小堆算法,二是利用扫描线策略。每种解法都附带了C++实现,并分析了它们的时间复杂度和空间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],…] (si < ei), find the minimum number of conference rooms required.
Example 1:
Input: [[0, 30],[5, 10],[15, 20]]
Output: 2
Example 2:
Input: [[7,10],[2,4]]
Output: 1

解法

解法1:利用最小堆算法

将所有interval的结束时间以最小堆储存,遍历整个interval,每次pop出最早结束的inteval时间,比较当前interval是否与最早结束的interval有重叠,如果有重叠,则无需pop出最早结束的interval,直接加入当前interval,说明需要多加一个room。否则的话,证明room数不需要变化,pop出最早结束的interval,把现在结束的interval push’到最小堆中。最后需要room的长度即为需要的room数

class Solution(object):
    def minMeetingRooms(self, intervals):
        """
        :type intervals: List[List[int]]
        :rtype: int
        """
        if not intervals:
            return 0
        intervals.sort(key=lambda x:x[0])
        free_rooms = []
        heapq.heappush(free_rooms,intervals[0][1])
        for i in intervals[1:]:
            if free_rooms[0]<=i[0]:
                heapq.heappop(free_rooms)
            heapq.heappush(free_rooms,i[1])
        return len(free_rooms)

C++版本:
两个注意点:

  • 利用priority queue作为heap
  • 构造compare函数排序
class Solution {
    static bool cmp(const vector<int>& left, const vector<int>& right){
        return left[0] < right[0] || (left[0] == right[0] && left[1] < right[1]);
    }
public:
    int minMeetingRooms(vector<vector<int>>& intervals) {
        if (intervals.empty() || intervals[0].empty()) return 0;
        sort(intervals.begin(),intervals.end(),cmp);
        priority_queue<int, vector<int>, greater<int>> pq;
        pq.push(intervals[0][1]);
        
        for(int i=1;i<intervals.size();i++){
            if(intervals[i][0]<pq.top()){
                pq.push(intervals[i][1]);
            }else{
                pq.pop();
                pq.push(intervals[i][1]);
            }
        }
        return pq.size();
        
    };
};

时间复杂度:O(Nlog(N)), 最小堆执行push和pop操作的复杂度为log(N),需要对N个元素中的所有元素进行一次操作
空间复杂度:O(N), 最坏的情况是需要N个room,那么N个元素都被用来构造最小堆了

解法2:利用扫描线

把所有的interval开始和结束时间进行排序,遍历这个排好序的数组,如果遇到有新会议开始则room数加一,遇到一个会议结束,room数减一,求出整个遍历过程中需要最大的room数便是答案。需要注意的是,当碰到一个一个interval的结束时间和另一个interval的开始时间相等时,需要先减1再加1,因为这种情况下不需要增加room数

class Solution(object):
    def minMeetingRooms(self, intervals):
        """
        :type intervals: List[List[int]]
        :rtype: int
        """
        if not intervals:
            return 0
        tmp = []
        for i in intervals:
            tmp.append((i[0],1))
            tmp.append((i[1],0))
        tmp.sort(key=lambda x:(x[0],x[1]))
        curr_max = 0
        final_max = 0
        for i in tmp:
            if i[1]==0:
                curr_max-=1
            else:
                curr_max+=1
            final_max = max(curr_max,final_max)
        return final_max

C++版本

class Solution {
    static bool cmp(const vector<int>& left, const vector<int>& right){
        return left[0] < right[0] || (left[0] == right[0] && left[1] < right[1]);
    }
public:
    int minMeetingRooms(vector<vector<int>>& intervals) {
        vector<vector<int>> times;
        for(auto interval : intervals){
            times.push_back({interval[0],1});
            times.push_back({interval[1],0});
        }
        sort(times.begin(),times.end(),cmp);
        
        int count = 0;
        int ans = 0;
        for(auto time : times){
            if(time[1] == 0){
                count -= 1;
            }else{
                count += 1;
            }
            ans = max(ans,count);
        }
        return ans;
    }
};

如果vector元素是pair,无需手动定义compare,因为pair会自动比较第一个,然后在比较第二个

class Solution {
public:
    int minMeetingRooms(vector<vector<int>>& intervals) {
        vector<pair<int,int>> times;
        for(auto interval : intervals){
            times.push_back({interval[0],1});
            times.push_back({interval[1],0});
        }
        sort(times.begin(),times.end());
        
        int count = 0;
        int ans = 0;
        for(auto time : times){
            if(time.second == 0){
                count -= 1;
            }else{
                count += 1;
            }
            ans = max(ans,count);
        }
        return ans;
    }
};

时间复杂度和空间复杂度:与解法1相同

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值