大、小堆 - 模拟 -leetcode-1801. 积压订单中的订单总数

1801. 积压订单中的订单总数





大、小堆 - 模拟

写的有点小复杂,大佬勿喷。只是记录一下自己的做题思路。

思路:

  1. 使用“小根堆 --> sellQueue 积压队列”、“大根堆 --> buyQueue 积压队列”;
  2. “采购”订单
    • “没人卖”、或“因为本次采购手里钱不够,而买不起”时,则直接将当前采购订单积压到 buyQueue,即可;
    • 本次采购能买得起时,则持续“采购”直至(对应 while )“钱不足”、或“本次订单需求完事儿了” 、或 “已经没有商品可以采购了”;(while 的 3 个循环条件)
      • 采购订单数较少时,则将销售订单减去采购订单数后,重新入sellQueue,并结束本轮“采购”;–> amount = 0;
      • 采购订单较多时,本次购买后,继续“尝试”购买. --> amount -= top.amount;
    • 若“持续采购”结束后,本次还剩余没有采购的订单,则加入积压到 buyQueue
  3. “销售”订单
    逻辑同上“采购订单”中…
class Order {
     int amount;
     int price;

     public Order(int amount, int price) {
         this.amount = amount;
         this.price = price;
     }

     @Override
     public String toString() {
         return "Order{" +
                 "amount=" + amount +
                 ", price=" + price +
                 '}';
     }
 }

class Solution {
    public int getNumberOfBacklogOrders(int[][] orders) {
        // 小根堆 --> sell 积压
        Queue<Order> sellQueue = new PriorityQueue<>((order1, order2) -> {
            return order1.price - order2.price;
        });
        // 大根堆 --> buy 积压
        Queue<Order> buyQueue = new PriorityQueue<>((order1, order2) -> {
            return order2.price - order1.price;
        });
        int res = 0;
        final int MOD = (int) (1e9 + 7);
        for (int i = 0; i < orders.length; i++) {
            int price = orders[i][0];
            int amount = orders[i][1];
            int type = orders[i][2];
            if (type == 0) { // buy
                // “没人卖”或“手里钱不够,买不起”时,则直接将当前采购订单积压到buyQueue,即可
                if (sellQueue.isEmpty() || price < sellQueue.peek().price) {
                    buyQueue.offer(new Order(amount, price));
                    continue;
                }
                // 能买得起
                while (!sellQueue.isEmpty() && price >= sellQueue.peek().price && amount > 0) {
                    Order top = sellQueue.poll();
                    // 采购订单数较少时,则将销售订单减去采购订单数后,重新入sellQueue
                    if (amount < top.amount) {
                        top.amount -= amount;
                        amount = 0; // 本次采购需求 全部解决
                        sellQueue.offer(top);
                    } else { // 采购订单较多时,本次购买后,继续尝试购买
                        amount -= top.amount;
                    }
                }
                // 本次还剩余没有采购的订单,则加入积压到buyQueue
                if (amount > 0) {
                    buyQueue.offer(new Order(amount, price));
                }
            } else { // sell
                // “没人买”或“卖的价格太贵,卖不掉”时,则直接将当前销售订单积压到sellQueue,即可
                if (buyQueue.isEmpty() || price > buyQueue.peek().price) {
                    sellQueue.offer(new Order(amount, price));
                    continue;
                }
                //
                while (!buyQueue.isEmpty() && price <= buyQueue.peek().price && amount > 0) {
                    Order top = buyQueue.poll();
                    // 销售订单数较少时,则采购订单减去销售订单数后,重新入buyQueue
                    if (amount < top.amount) {
                        top.amount -= amount;
                        amount = 0; // 本次销售需求 全部解决
                        buyQueue.offer(top);
                    } else { // 销售订单较多时,本次销售后,继续尝试销售
                        amount -= top.amount;
                    }
                }
                // 本次还剩余没有销售的订单,则加入积压到sellQueue
                if (amount > 0) {
                    sellQueue.offer(new Order(amount, price));
                }
            }
        }
        // 统计两个队列中所有订单号
        for (Order order : sellQueue) {
            res = (res + order.amount) % MOD;
        }
        for (Order order : buyQueue) {
            res = (res + order.amount) % MOD;
        }
        return res;
    }

    public static void main(String[] args) {
        // int[][] orders = {{10,5,0},{15,2,1},{25,1,1},{30,4,0}};
        int[][] orders = {{7,1000000000,1},{15,3,0},{5,999999995,0},{5,1,1}};
        System.out.println(new Solution().getNumberOfBacklogOrders(orders));
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值