一日一练: 积压订单中的订单总数

136 阅读2分钟

积压订单中的订单总数

这道题在于题目的理解。这里有两种未执行的积压订单,销售订单sell采购订单buy。提交订单时,如果当前订单:

  • 是采购订单,去积压的销售订单中查找价格最低的
  • 是销售订单,需要去积压的采购订单中去查找价格最高的

从价格最低和最高可以确定这里可以使用堆排序。需要去销售积压订单中查找最小值,用小顶堆;需要在采购积压订单中查找最大值,用大顶堆

具体思路:

  • 判断是何种订单
    • 采购订单
      • 是否有积压销售订单
        • 没有:将采购订单加入积压采购订单
        • 有:比较采购价格是否大于销售积压订单中的最小值,
          • 积压订单数量与当前采购订单的数量关系
            • 积压销售订单大于采购订单: 清空采购订单,减小积压销售订单数量
            • 积压销售订单等于采购订单:清空采购订单和积压销售订单
            • 积压销售订单小于采购订单:清空当前价格的积压销售订单,减小采购订单;寻找下一个最小价格的积压销售订单;继续比较数量。。。
    • 销售订单
      • 是否有积压的采购订单
        • 没有

        • 有 。。。(这里的比较和上述相似,只是这里是取最大值)

代码:

大小堆的实现可以参考专栏的前几篇文章,因为要实现最大和最小堆,如果把代码也贴过来,代码的就太长了。

// 大顶堆 MaxBinaryHeap
// 小顶堆 MinBinaryHeap

const getNumberOfBacklogOrders = function (orders) {
  // 大顶堆 积压的采购订单
  const buyBlocks = new MaxBinaryHeap()
  // 小顶堆 积压的销售订单
  const sellBlocks = new MinBinaryHeap()
  for (let i = 0; i < orders.length; i++) {
    const order = orders[i]
    if (order[2] === 0) {
      // 当前为采购订单,但是没有积压销售订单,直接将采购订单加入积压
      if (sellBlocks.length === 0) {
        buyBlocks.insert(order)
      } else {
        // 找到积压的销售订单比当前采购订单 价格 低的积压订单
        // 从最小值开始
        if (sellBlocks.top[0] <= order[0]) {
          while (sellBlocks.length && order[1] > 0 && sellBlocks.top[0] <= order[0]) {
            let minSell = sellBlocks.pop()
            let diff = minSell[1] - order[1]
            if (diff < 0) {
              // 当前订单还需要采购,继续在积压销售订单中查找
              order[1] = -diff
            } else if (diff >= 0) {
              // 清空
              minSell[1] = diff
              order[1] = 0
              sellBlocks.insert(minSell)
            }
          }          
        }
        // 如果当前订单没有被清空,加入积压订单
        if (order[1] !== 0) {
            buyBlocks.insert(order)
        }
      }
    } else {
      if (buyBlocks.length === 0) {
        sellBlocks.insert(order)
      } else {
        // 找到积压的采购订单比当前销售订单 价格 高的积压订单
        // 从最大值开始
        if (buyBlocks.top[0] >= order[0]) {
          while(buyBlocks.length && order[1] > 0 && buyBlocks.top[0] >= order[0]) {
            const maxBuy = buyBlocks.pop()
            let diff = maxBuy[1] - order[1]
            if (diff < 0) {
              order[1] = -diff
            } else if (diff >= 0) {
              maxBuy[1] = diff
              order[1] = 0
              buyBlocks.insert(maxBuy)
            }
          }
          
        }
        if (order[1] !== 0) {
            sellBlocks.insert(order)
        }
      }
    }
  }

  let size = 0
  while (sellBlocks.length) {
    const v = sellBlocks.pop()
    size += v[1]
  }

  while (buyBlocks.length) {
    const v = buyBlocks.pop()
    size += v[1]
  }
  return size % (Math.pow(10, 9) + 7)
}