这个题本质也是考,大顶堆和小顶堆,助教讲解的方法直接用到了,优先队列直接使用lodash的 priority-queue,这个代码库来实现大顶堆和小顶堆,又点儿看不懂.. 看了题解 发现有个也是用大小顶堆为思路实现的,并且是自己写的大小顶堆,比这撸了一遍,发现它写的代码更简洁,
/**
* @param {number[][]} orders
* @return {number}
*/
var getNumberOfBacklogOrders = function(orders) {
// sell 小顶堆
let minHeap = new Heap();
// 节点结构为 [price, amount]
// 根据节点price构建堆
var cmp = (a, b) => a[0] < b[0];
// buy 大顶堆
let maxHeap = new Heap(cmp);
for (let arr of orders) {
// buy时 看 sell小顶堆
if (arr[2] == 0) {
while (true) {
// 小顶堆堆顶订单数量足够抵消 buy订单数量,还有剩余时
if (minHeap.heap.length > 0 && minHeap.heap[0][0] <= arr[0] && minHeap.heap[0][1] > arr[1]) {
// 小顶堆堆顶订单数量为 抵消buy订单后 余下的数量
minHeap.heap[0][1] = minHeap.heap[0][1]-arr[1];
break;
// 小顶堆堆顶订单数量全部抵消 buy订单数量, 或者不够抵消时
} else if (minHeap.heap.length > 0 && minHeap.heap[0][0] <= arr[0] && minHeap.heap[0][1] <= arr[1]){
// 还剩下的buy订单,待会和重构的sell小顶堆重新匹配
arr[1] -= minHeap.heap[0][1];
// 移除sell小顶堆堆顶
minHeap.heap[0] = minHeap.heap[minHeap.heap.length-1];
minHeap.heap.pop();
minHeap.down(0);
// 剩余订单为0,退出循环
} else if (arr[1] == 0) {
break;
// 阻塞了,剩下订单全堆积
} else {
maxHeap.heap.push([arr[0], arr[1]]); // 节点结构是 [price, amount]
maxHeap.up(maxHeap.heap.length-1);
break;
}
}
// sell时 看 buy大顶堆
} else {
while (true) {
if (maxHeap.heap.length > 0 && maxHeap.heap[0][0] >= arr[0] && maxHeap.heap[0][1] > arr[1]) {
// 大顶堆堆顶订单数量为 抵消sell订单后 余下的数量
maxHeap.heap[0][1] = maxHeap.heap[0][1]-arr[1];
break;
} else if (maxHeap.heap.length > 0 && maxHeap.heap[0][0] >= arr[0] && maxHeap.heap[0][1] <= arr[1]){
// 还剩下的sell订单,待会和重构的buy大顶堆重新匹配
arr[1] -= maxHeap.heap[0][1];
// 移除buy大顶堆堆顶
maxHeap.heap[0] = maxHeap.heap[maxHeap.heap.length-1];
maxHeap.heap.pop();
maxHeap.down(0);
// 剩余订单为0,退出循环
} else if (arr[1] == 0) {
break;
// 阻塞了,剩下的全堆积
} else {
minHeap.heap.push([arr[0], arr[1]]); // 节点结构为 [price, amount]
minHeap.up(minHeap.heap.length-1);
break;
}
}
}
}
let count = 0;
// 积压订单数为两个堆每个节点积压的订单数
for (let arr of maxHeap.heap) {
count += arr[1];
}
for (let arr of minHeap.heap) {
count += arr[1];
}
return count % 1000000007;
};
// 默认小顶堆
var defaultCmp = (a, b) => a[0] > b[0];
class Heap {
constructor(cmp=defaultCmp) {
this.heap = []; // 每个节点结构是 [price, amount]
this.cmp = cmp;
}
up(i) {
while (i > 0) {
// 求父节点
const parent = (i - 1) >> 1;
if (this.cmp(this.heap[parent], this.heap[i])) {
[this.heap[parent], this.heap[i]] = [this.heap[i], this.heap[parent]];
i = parent;
} else {
break;
}
}
}
down(i) {
while (2 * i + 1 < this.heap.length) {
// 这个child是左子节点
let child = 2 * i + 1;
// child + 1 相当于2*i + 2 右子节点
if (child + 1 < this.heap.length && this.cmp(this.heap[child], this.heap[child + 1])) {
child++;
}
// a[0] > b[0]
//this.cmp(this.heap[i], this.heap[child])-》
//this.head[i][0]>this.head[child][0]
if (this.cmp(this.heap[i], this.heap[child])) {
[this.heap[child], this.heap[i]] = [this.heap[i], this.heap[child]];
i = child;
} else {
break;
}
}
}
}