记录 1 道算法题
积压订单中的订单总数
要求:
* 分为购买订单 buy 和销售订单 sell
* 推入 buy 订单的时候,当 buy 订单的价格大于等于 sell 订单的时候,进行抵消
* 推入 sell 订单的时候,当 sell 订单的价格小于等于 buy 订单的时候,进行抵消
解题思路是,当订单一个个推入的时候,就是一个比较的过程,所以如果按照升序或者降序来排序推入的订单的话,剩下的订单都是永远无法消除的订单。
这题和升序排序相关的话,我们可以用两个堆来做,只要保证堆顶是最大或者最小的,具体里面可以不用排序。
buy 订单是要大于等于 sell 订单才能消除,所以 buy 订单要降序排列,确保堆顶是 buy 里面的最大值。如果 buy 订单是越来越小的,那么当 buy 和 sell 订单错过了一轮,变成了积压状态时, sell 会越来越大,sell越来越小也无法确定他和 buy 缩小的速度一样。
sell 订单要小于等于 buy , 所以 sell 订单要升序排列,保证堆顶的是 sell 里面的最小值。
buy 越来越大,sell 越来越小,才有机会在某一个点出现 buy 大于 sell。
和堆相关的可以看另一篇文章
function getNumberOfBacklogOrders(orders) {
// 创建最大堆和最小堆
const maxHeap = new Heap((a, b) => a.price - b.price)
const minHeap = new Heap((a, b) => b.price - a.price)
// 为了方便比较,在里面插入一个伪订单。
maxHeap.push({ price: Infinity, amount: 0 })
minHeap.push({ price: -Infinity, amount: 0 })
// 这里是将订单一个个推入,因为使用了递归,所以封装成了独立函数
for (const [price, amount, type] of orders) {
if (type === 0) {
buy(price, amount)
} else if (type === 1) {
sell(price, amount)
}
}
// buy 订单使用的处理函数
function buy(price, amount) {
// 终结递归
if (amount == 0) return
// 比 buy 里面的大,可以用来抵消,如果不是最大的就直接推进去了
// 因为最大的已经比较过了,没有被消除,那比他小的就更不可能被消除
if (price > minHeap.data[0].price) {
// sell 小于等于 buy,可以抵消
if (maxHeap.data[0].price <= price) {
// sell 订单 - buy 订单 数量
const num = maxHeap.data[0].amount - amount
if (num <= 0) {
// 如果是负数或者0,都说明 sell 订单先消耗完
maxHeap.pop()
// 继续找下一个 sell 最小值 递归处理,直到数量0
buy(price, num * -1)
} else {
// buy 先消耗完,sell 订单数量更新
maxHeap.data[0].amount = num
}
} else {
// sell 大于 buy订单,不能抵消就把 buy 存起来
minHeap.push({ price, amount })
}
} else {
// buy 不是最大值, 存起来
minHeap.push({ price, amount })
}
}
// sell 和 上面的思路是一样的,比较谁的数量先消耗完。
function sell(price, amount) {
if (amount == 0) return
// 要 sell 的最小值
if (price < maxHeap.data[0].price) {
// sell 小于等于 buy
if (price <= minHeap.data[0].price) {
const num = minHeap.data[0].amount - amount
if (num <= 0) {
// 消耗,多余,递归
minHeap.pop()
sell(price, num * -1)
} else {
minHeap.data[0].amount = num
}
} else {
maxHeap.push({ price, amount })
}
} else {
maxHeap.push({ price, amount })
}
}
const add = (a, b) => {
return a + b.amount
}
// 最后需要把订单的 amount 加起来。
const count = minHeap.data.reduce(add, 0) + maxHeap.data.reduce(add, 0)
// leetcode的要求取余。
return count % (Math.pow(10, 9) + 7)
};
以上就是使用堆的解法,就是抵消订单的过程比较细腻,整体用到堆的思路,需要梳理 buy 和 sell 谁取最大值,谁取最小值。
结束