1353. Maximum Number of Events That Can Be Attended

368 阅读1分钟

题目描述

leetcode-cn.com/problems/ma…

分析

如果在某个时间点,有多个会可以开

根据贪心,应该开的是最早结束的会议

算法

贪心,堆

过程

统计时间点对应的所有可开会议 -> 遍历所有时间点 -> 将当前时间点的所有会议放到堆中 -> 堆弹出所有不合法会议 -> 去除一个结束时间最早的会议并递增结果

统计

用一个数组,统计所有的时间点(最大为 Math.pow(10, 5)) 可以开的所有会议

遍历时间

从 1 开始,一直遍历到最大时间 MAX,首先在堆中放入当前时间下所有可开的会议

我们要做的是,在这个时间点,优先开最早结束的会议,因为这样可以达到最优结果,即开最多的会

统计结果

先弹出所有不合法的会议,即开会时间没发满足当前时间点的

然后弹出一个在这个时间点要去开的会议,递增统计结果

代码

/**
       * @param {number[][]} events
       * @return {number}
       */
      var maxEvents = function (events) {
        const n = events.length,
          max = Math.pow(10, 5),
          left = new Array(max + 1).fill(0).map(() => new Array()),
          h = new Heap((a, b) => {
            if (b === undefined) return false
            return a[1] > b[1]
          })

        let ans = 0

        for (let i = 0; i < n; i++) {
          const e = events[i]
          left[e[0]].push(e)
        }
        for (let i = 1; i <= max; i++) {
          for (const x of left[i]) {
            if (x[0] <= i) h.insert(x)
          }
          while (!h.isEmpty() && h.top()[1] < i) h.extract()
          if (!h.isEmpty()) {
            h.extract()
            ans++
          }
        }

        return ans
      }
      class Heap {
        constructor(compareFn) {
          this.compareFn = compareFn
          this.heap = []
        }

        getLeftIndex(index) {
          return index * 2 + 1
        }

        getRightIndex(index) {
          return index * 2 + 2
        }

        getParentIndex(index) {
          return Math.floor((index - 1) / 2)
        }

        size() {
          return this.heap.length
        }

        isEmpty() {
          return this.size() === 0
        }

        swap(parent, index) {
          const arr = this.heap;
          ;[arr[parent], arr[index]] = [arr[index], arr[parent]]
        }

        insert(value) {
          const index = this.heap.length
          this.heap.push(value)
          this.siftUp(index)
        }

        siftUp(index) {
          let parent = this.getParentIndex(index)

          while (
            index > 0 &&
            this.compareFn(this.heap[parent], this.heap[index])
          ) {
            this.swap(parent, index)
            index = parent
            parent = this.getParentIndex(index)
          }
        }

        extract() {
          if (this.isEmpty()) return
          if (this.size() === 1) return this.heap.pop()
          const removedItem = this.heap[0]
          this.heap[0] = this.heap.pop()
          this.siftDown(0)

          return removedItem
        }

        siftDown(index) {
          let element = index
          const left = this.getLeftIndex(index)
          const right = this.getRightIndex(index)

          if (
            index < this.size() &&
            this.compareFn(this.heap[element], this.heap[left])
          ) {
            element = left
          }

          if (
            index < this.size() &&
            this.compareFn(this.heap[element], this.heap[right])
          ) {
            element = right
          }

          if (element !== index) {
            this.swap(element, index)
            this.siftDown(element)
          }
        }

        top() {
          return this.heap[0]
        }
      }