小跟堆-1353. 最多可以参加的会议数目

59 阅读1分钟

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

给你一个数组 events,其中 events[i] = [startDayi, endDayi] ,表示会议 i 开始于 startDayi ,结束于 endDayi 。

你可以在满足 startDayi <= d <= endDayi 中的任意一天 d 参加会议 i 。注意,一天只能参加一个会议。

请你返回你可以参加的 最大 会议数目。

 

示例 1:

输入: events = [[1,2],[2,3],[3,4]]
输出: 3
解释: 你可以参加所有的三个会议。
安排会议的一种方案如上图。
第 1 天参加第一个会议。
第 2 天参加第二个会议。
第 3 天参加第三个会议。

示例 2:

输入: events= [[1,2],[2,3],[3,4],[1,2]]
输出: 4

 

提示: ​​​​​​

  • 1 <= events.length <= 105
  • events[i].length == 2
  • 1 <= startDayi <= endDayi <= 105
/**
 * @param {number[][]} events
 * @return {number}
 */
var maxEvents = function(events) {
	events.sort((a, b) => a[0] - b[0]);

	const heap = new Heap((a, b) => a < b)
	let curDay = 1;
	let i = 0;
	let result = 0;

	while (i < events.length || heap.getTop()) {
		// 将所有开始时间等于当天的会议的结束时间放入小跟堆
		while (i < events.length && events[i][0] === curDay) {
			heap.push(events[i][1]);
			i++;
		}

		// 将所有已经结束的会议剔除小跟堆
		while (heap.getTop() && heap.getTop() < curDay) {
			heap.pop();
		}

		if (heap.getTop()) {
			heap.pop();
			result++;
		}
		curDay++
	}
	return result;
}

class Heap {
	constructor(compare) {
		this.nodeList = [];
		this.compare = typeof compare === 'function' ? compare : defaultCompare;
	}

	defaultCompare(a, b) {
		return a > b;
	}

	getTop() {
		if (this.nodeList.length) {
			return this.nodeList[0];
		}
		return null;
	}

	push(val) {
		this.nodeList.push(val);
		this.up(this.nodeList.length - 1);
	}

	parent(index) {
		return index % 2 === 0 ? index / 2 - 1 : (index - 1) / 2;
	}

	up(index) {
		const { parent, compare, nodeList } = this;
		let curIndex = index;
		while (curIndex > 0 && compare(nodeList[curIndex], nodeList[parent(curIndex)])) {
			const temp = nodeList[parent(curIndex)];
			nodeList[parent(curIndex)] = nodeList[curIndex];
			nodeList[curIndex] = temp;
			curIndex = parent(curIndex);
		} 
	}

	pop() {
		const { nodeList } = this;
		if (!nodeList.length) {
			return null;
		}

		const top = nodeList[0];
		nodeList[0] = nodeList[nodeList.length - 1];
		nodeList.pop();
		this.down(0);
		return top;
	}

	left(index) {
		return index * 2 + 1;
	}

	right(index) {
		return index * 2 + 2;
	}

	down(index) {
		const { left, right, compare, nodeList } = this;
		let curIndex = index;
		while (left(curIndex) < nodeList.length) {
			let target = left(curIndex);
			if (right(curIndex) < nodeList.length && compare(nodeList[right(curIndex)], nodeList[left(curIndex)])) {
				target = right(curIndex);
			}

			if (compare(nodeList[curIndex], nodeList[target])) {
				break;
			}

			const temp = nodeList[target];
			nodeList[target] = nodeList[curIndex];
			nodeList[curIndex] = temp;
			curIndex = target;
		}
	}
}