[路飞]最多可参加的会议数目

73 阅读2分钟

记录 1 道算法题

最多可参加的会议数目

leetcode-cn.com/problems/ma…


要求:提供一个二维数组,每一个元素为[开始日期,结束日期]。在这个日期范围内都可以参加这个会议,经过分配,返回可以参加的最多的会议数目。

比如:[[1,2],[2,3],[3,4]],输出:3。 [[1,2],[2,3],[3,4],[1,2]],输出:4。

用贪心的算法解题,尽可能先完成结束日期早的会议,就能参加更多的会议。因为如果早结束的会议不参加而先参加晚结束的会议,就会导致错过早结束的会议。

首先先以开始时间为 key,收集同一天开始的会议。同时记录最晚的会议结束时间。因为可以一直参加,直到没有会议,所以以最后的会议为结束。

然后动态的计算最早结束的会议需要用到小顶堆,我们可以很方便从堆顶拿到最早结束的会议。

从开始时间里面一一拿出当天开始的会议,然后存入堆中。接下来从堆中取出最早结束的会议。只取一个会议,然后结束时间小于今天的会议从堆中清除,由于是小顶堆,只需要一直 pop 就行。

由于每次只取一个会议,但是当天开始的会议会有很多个。所以每次堆中会留有以前开始的会议,然后再追加今天开始的会议。这样就动态的维护了一个会议记录。

    function maxEvents(events) {
        const map = {}
        let max = 0
        for(const [start, end] of events) {
            // 找到最晚结束的会议
            max = Math.max(max, end)
            // 存储同一天开始的会议
            let set = map[start]
            if (!set) {
                mas[start] = set = []
            }
            set.push(end)
        }
        // 到最后一天为止都可以参加会议
        // 小根堆
        let count = 0
        const heap = new Heap((a, b) => a - b)
        // 因为 max 是最后一天,所以包括 max
        for(let i = 0; i <= max; i++) {
            const set = map[i]
            // 将第 i 天开始的会议存入堆中
            for(let j = 0; set && j < set.length; j++) {
                heap.push(set[j])
            }
            // 堆内还有会议
            if (heap.size() > 0) {
                // 取出一个会议
                heap.pop()
                count++
                // 将结束日期为今天或今天之前的会议清除
                while(heap.data[0] <= i) {
                    heap.pop()
                }
            }
        }
        
        return count
    }