力扣每日打卡:230102优先队列应用
1801. 积压订单中的订单总数
难点:
- 使用优先队列
- 需求分析两个队列的使用场景,需求梳理不清容易混淆。
1. 需求梳理
orders[i] = [pricei, amounti, orderTypei]
可获取的参数为二维数组,对这个二维数组的数据进行处理,需要进行抵消操作,需要维护两组数据,如果我想买入,查看卖出的最低价格,进行抵消,如果我想卖出,查看买入数据中的最高价格。
这里产生了两组判断逻辑
- 判读是买入还是卖出
- 判断是否能够抵消=是否有大于或者小于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;
}
}