leetcode 1801. 积压订单中的订单总数
问题描述: 给你一个二维整数数组 orders ,其中每个 orders[i] = [pricei, amounti, orderTypei] 表示有 amounti 笔类型为 orderTypei 、价格为 pricei 的订单。
订单类型 orderTypei 可以分为两种:
0表示这是一批采购订单buy1表示这是一批销售订单sell
注意,orders[i] 表示一批共计 amounti 笔的独立订单,这些订单的价格和类型相同。对于所有有效的 i ,由 orders[i] 表示的所有订单提交时间均早于 orders[i+1] 表示的所有订单。
存在由未执行订单组成的 积压订单 。积压订单最初是空的。提交订单时,会发生以下情况:
- 如果该订单是一笔采购订单
buy,则可以查看积压订单中价格 最低 的销售订单sell。如果该销售订单sell的价格 低于或等于 当前采购订单buy的价格,则匹配并执行这两笔订单,并将销售订单sell从积压订单中删除。否则,采购订单buy将会添加到积压订单中。 - 反之亦然,如果该订单是一笔销售订单
sell,则可以查看积压订单中价格 最高 的采购订单buy。如果该采购订单buy的价格 高于或等于 当前销售订单sell的价格,则匹配并执行这两笔订单,并将采购订单buy从积压订单中删除。否则,销售订单sell将会添加到积压订单中。
输入所有订单后,返回积压订单中的 订单总数 。由于数字可能很大,所以需要返回对 109 + 7 取余的结果。
示例 1:
输入: orders = [[10,5,0],[15,2,1],[25,1,1],[30,4,0]]
输出: 6
解释: 输入订单后会发生下述情况:
- 提交 5 笔采购订单,价格为 10 。没有销售订单,所以这 5 笔订单添加到积压订单中。
- 提交 2 笔销售订单,价格为 15 。没有采购订单的价格大于或等于 15 ,所以这 2 笔订单添加到积压订单中。
- 提交 1 笔销售订单,价格为 25 。没有采购订单的价格大于或等于 25 ,所以这 1 笔订单添加到积压订单中。
- 提交 4 笔采购订单,价格为 30 。前 2 笔采购订单与价格最低(价格为 15)的 2 笔销售订单匹配,从积压订单中删除这 2 笔销售订单。第 3 笔采购订单与价格最低的 1 笔销售订单匹配,销售订单价格为 25 ,从积压订单中删除这 1 笔销售订单。积压订单中不存在更多销售订单,所以第 4 笔采购订单需要添加到积压订单中。
最终,积压订单中有 5 笔价格为 10 的采购订单,和 1 笔价格为 30 的采购订单。所以积压订单中的订单总数为 6 。
思路: 用两个堆来维护销售跟购买订单
/**
* @param {number[][]} orders
* @return {number}
*/
var getNumberOfBacklogOrders = function(orders) {
let buy=new Heap((a,b)=>a[0]>b[0]);
let sell=new Heap((a,b)=>a[0]<b[0]);
for(let i=0;i<orders.length;i++){
if(orders[i][2]===0){
while(orders[i][1]>0&&sell.size>0&&sell.top[0]<=orders[i][0]){
let res=Math.min(orders[i][1],sell.top[1]);
orders[i][1]-=res;
sell.top[1]-=res;
if(sell.top[1]==0)sell.pop()
}
if(orders[i][1]!=0)buy.push(orders[i])
}else{
while(orders[i][1]>0&&buy.size>0&&buy.top[0]>=orders[i][0]){
let res=Math.min(orders[i][1],buy.top[1]);
orders[i][1]-=res;
buy.top[1]-=res;
if(buy.top[1]==0)buy.pop()
}
if(orders[i][1]!=0)sell.push(orders[i])
}
}
let sum=0;
for(let item of buy.getData()){
sum=(sum+item[1])%1000000007
}
for(let item of sell.getData()){
sum=(sum+item[1])%1000000007
}
return sum
};
class Heap {
constructor(cmp) {
this.data = [];
this.cmp = cmp;
}
get size() {
return this.data.length;
}
get top() {
return this.data[0];
}
getData() {
return this.data;
}
swap(i, j) {
[this.data[i], this.data[j]] = [this.data[j], this.data[i]];
}
// 向上冒泡
up(i) {
let index=this.data.length-1;
while(index>0){
let p=Math.floor((index-1)/2);
if(p>=0&&this.cmp(this.data[index],this.data[p])){
this.swap(index,p);
index=p;
}else{
break;
}
}
}
// 下沉操作
down(i) {
if(this.data.length<2)return;
let index=0,l=2*index+1,len=this.data.length;
while(l<len){
let r=l+1;
if(r<len&&this.cmp(this.data[r], this.data[l]))l=r;
if(this.cmp(this.data[index], this.data[l]))break;
this.swap(index,l)
index=l;
l=index*2+1;
}
}
push(item) {
this.data.push(item);
this.up();
}
//删除堆顶元素
pop() {
this.swap(0, this.data.length - 1);
const res = this.data.pop();//已删除的元素(原来的堆顶元素)
this.down();
return res;
}
}