[路飞] 积压订单中的订单总数

143 阅读2分钟

记录 1 道算法题

积压订单中的订单总数

leetcode-cn.com/problems/nu…


要求:

    * 分为购买订单 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 谁取最大值,谁取最小值。

结束