力扣每日打卡:优先队列的应用

力扣每日打卡:230102优先队列应用

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

难点:

  1. 使用优先队列
  2. 需求分析两个队列的使用场景,需求梳理不清容易混淆。

1. 需求梳理

orders[i] = [pricei, amounti, orderTypei]

可获取的参数为二维数组,对这个二维数组的数据进行处理,需要进行抵消操作,需要维护两组数据,如果我想买入,查看卖出的最低价格,进行抵消,如果我想卖出,查看买入数据中的最高价格。

这里产生了两组判断逻辑

  1. 判读是买入还是卖出
  2. 判断是否能够抵消=是否有大于或者小于n的数据存在&&库存数量满足条件。
1.扫描到0,即买入单,去访问卖出队列sell_q数据匹配,所以sell_q是最小值优先出队。
2.扫描到1,即卖出单,去访问卖出队列buy_q数据匹配,所以buy_q是最大值优先出队。

2. 存储的数据结构的设计。

我一开始的思路是这样的,直接去扫描这个二维数组。抵消的话置为0;或者数量减去抵消数量。

  • 假如是买入数据,去扫描之前的卖出数据,如果卖出数据小于买入数据的话,还要去寻找最低的卖出数据,所以原地扫描是行不通的。

首先数据要区分先后,而且每次都要从小到大或者从大到小排序,区分先后就可以用队列,有序的话就联想到了优先队列。

2.1 优先队列(使用lambda设置排序规则)

2.11 盲点:lambda中区分升序还是降序。

java中PriorityQueue采用的是堆排序,可以根据Comparator来设置排序规则。

public class firewolf20230102 {
    public static void main(String[] args) {
        PriorityQueue<Integer> queue  = new PriorityQueue<>();
        queue.add(1);
        queue.add(9);
        queue.add(-1);
        System.out.println(queue.poll());
        System.out.println(queue.poll());
        System.out.println(queue.poll());
//        -1
//        1
//        9     可见优先队列 出队默认是增序,小根堆。
    }
    
}
    public static void main(String[] args) {
        PriorityQueue<Integer> queue  = new PriorityQueue<Integer>((a,b)->b-a);
        queue.add(1);
        queue.add(9);
        queue.add(-1);
        System.out.println(queue.poll());
        System.out.println(queue.poll());
        System.out.println(queue.poll());
//        9
//        1
//       -1
    }

但是卖出价格队列要求是大根堆,所以如何设置优先队列为降序?设置Comparator

b[0]-a[0]为返回值

class Solution {
    public int getNumberOfBacklogOrders(int[][] orders) {
        
        PriorityQueue<int[]> buy_q = new PriorityQueue<>((a,b)->b[0]-a[0]);//价格高的先出队列,大根堆。
        PriorityQueue<int[]> sell_q= new PriorityQueue<>((a, b) -> a[0]-b[0]);//a[0]-b[0] 代表了比较器comparater的返回值。小根堆。
        for(int[] order:orders){
            int price = order[0];
            int num = order[1];
            int type = order[2];
            if(type==0){
                //采购订单
                while (!sell_q.isEmpty()&&num>0&&price>=sell_q.peek()[0]){
                    //取出订单,做减法
                    int[] get_order = sell_q.poll();
                    if(get_order[1]>num){
                        get_order[1] = get_order[1] - num;
                        sell_q.add(get_order);
                        num = 0;
                    }else{
                        num-=get_order[1];
                    }
                }

                if(num > 0){
                    buy_q.add(new int[]{price, num});
                }
            }else {
                //卖出订单
                while (!buy_q.isEmpty()&&num>0&&buy_q.peek()[0]>=price){
                    int[] get_order = buy_q.poll();
                    if(get_order[1]>num){
                        get_order[1] = get_order[1] - num;
                        buy_q.add(get_order);
                        //这是我碰到的卡点,num值需要设置为0,来触发剩余量入队。
                        num = 0;
                    }else{
                        num-=get_order[1];
                    }
                }

                if(num>0){
                    sell_q.add(new int[]{price,num});
                }
            }
        }
        // 这里res要记录总数
        int res = 0;
        while (!sell_q.isEmpty()){
            int[] get_order = sell_q.poll();
            res = (res+get_order[1])%1000000007;
        }

        while (!buy_q.isEmpty()){
            int[] get_order = buy_q.poll();
            res = (res+get_order[1])%1000000007;
        }
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值