Course Schedule III
HardArrayGreedySortingHeap (Priority Queue)
Solution
class Heap {
heap: number[];
constructor() {
this.heap = [];
}
get length() {
return this.heap.length;
}
get peek(): number {
return this.heap[0] || 0;
}
get isEmpty() {
return this.length === 0;
}
private swap(index1: number, index2: number): void {
[this.heap[index1], this.heap[index2]] = [this.heap[index2], this.heap[index1]];
}
private parentIndex(index: number): number {
return (index - 1) >> 1;
}
private leftIndex(index: number): number {
return (index << 1) + 1;
}
private rightIndex(index: number): number {
return (index << 1) + 2;
}
private shiftDown(): void {
let currentIndex = 0;
while (this.leftIndex(currentIndex) < this.length) {
const leftIndex = this.leftIndex(currentIndex);
const rightIndex = this.rightIndex(currentIndex);
const childIndex =
rightIndex < this.length && this.heap[rightIndex] < this.heap[leftIndex]
? rightIndex
: leftIndex;
if (this.heap[currentIndex] <= this.heap[childIndex]) {
return;
}
this.swap(currentIndex, childIndex);
currentIndex = childIndex;
}
}
private shiftUp(): void {
let currentIndex = this.length - 1;
while (0 < currentIndex) {
const parentIndex = this.parentIndex(currentIndex);
if (this.heap[parentIndex] <= this.heap[currentIndex]) {
return;
}
this.swap(currentIndex, parentIndex);
currentIndex = parentIndex;
}
}
push(item: number): void {
this.heap.push(item);
this.shiftUp();
}
pop(): number {
if (this.length <= 1) {
return this.heap.pop() || 0;
}
const result = this.peek;
this.swap(0, this.length - 1);
this.heap.pop();
this.shiftDown();
return result;
}
}
export function scheduleCourse(courses: [number, number][]): number {
let current = 0;
const heap = new Heap();
courses.sort((a, b) => a[1] - b[1]);
courses.forEach(([duration, lastDay]) => {
if (current + duration <= lastDay) {
heap.push(-duration);
current += duration;
} else if (!heap.isEmpty && duration < -heap.peek) {
current += duration + heap.pop();
heap.push(-duration);
}
});
return heap.length;
}