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

172 阅读5分钟

题目描述

给你一个二维整数数组 orders ,其中每个 orders[i] = [pricei, amounti, orderTypei] 表示有 amounti 笔类型为 orderTypei 、价格为 pricei 的订单。

订单类型 orderTypei 可以分为两种:

  • 0 表示这是一批采购订单 buy
  • 1 表示这是一批销售订单 sell 注意,orders[i] 表示一批共计 amounti 笔的独立订单,这些订单的价格和类型相同。对于所有有效的 i ,由 orders[i] 表示的所有订单提交时间均早于 orders[i+1] 表示的所有订单。

存在由未执行订单组成的 积压订单 。积压订单最初是空的。提交订单时,会发生以下情况:

  • 如果该订单是一笔采购订单 buy ,则可以查看积压订单中价格 最低 的销售订单 sell 。如果该销售订单 sell 的价格 低于或等于 当前采购订单 buy 的价格,则匹配并执行这两笔订单,并将销售订单 sell 从积压订单中删除。否则,采购订单 buy 将会添加到积压订单中。
  • 反之亦然,如果该订单是一笔销售订单 sell ,则可以查看积压订单中价格 最高 的采购订单 buy 。如果该采购订单 buy 的价格 高于或等于 当前销售订单 sell 的价格,则匹配并执行这两笔订单,并将采购订单 buy 从积压订单中删除。否则,销售订单 sell 将会添加到积压订单中。 输入所有订单后,返回积压订单中的 订单总数 。由于数字可能很大,所以需要返回对 109 + 7 取余的结果。

 

示例 1:

image.png

输入:orders = [[10,5,0],[15,2,1],[25,1,1],[30,4,0]]
输出:6
解释:输入订单后会发生下述情况:
- 提交 5 笔采购订单,价格为 10 。没有销售订单,所以这 5 笔订单添加到积压订单中。
- 提交 2 笔销售订单,价格为 15 。没有采购订单的价格大于或等于 15 ,所以这 2 笔订单添加到积压订单中。
- 提交 1 笔销售订单,价格为 25 。没有采购订单的价格大于或等于 25 ,所以这 1 笔订单添加到积压订单中。
- 提交 4 笔采购订单,价格为 30 。前 2 笔采购订单与价格最低(价格为 15)的 2 笔销售订单匹配,从积压订单中删除这 2 笔销售订单。第 3 笔采购订单与价格最低的 1 笔销售订单匹配,销售订单价格为 25 ,从积压订单中删除这 1 笔销售订单。积压订单中不存在更多销售订单,所以第 4 笔采购订单需要添加到积压订单中。
最终,积压订单中有 5 笔价格为 10 的采购订单,和 1 笔价格为 30 的采购订单。所以积压订单中的订单总数为 6

示例 2:

image.png

输入:orders = [[7,1000000000,1],[15,3,0],[5,999999995,0],[5,1,1]]
输出:999999984
解释:输入订单后会发生下述情况:
- 提交 109 笔销售订单,价格为 7 。没有采购订单,所以这 109 笔订单添加到积压订单中。
- 提交 3 笔采购订单,价格为 15 。这些采购订单与价格最低(价格为 7 )的 3 笔销售订单匹配,从积压订单中删除这 3 笔销售订单。
- 提交 999999995 笔采购订单,价格为 5 。销售订单的最低价为 7 ,所以这 999999995 笔订单添加到积压订单中。
- 提交 1 笔销售订单,价格为 5 。这笔销售订单与价格最高(价格为 5 )的 1 笔采购订单匹配,从积压订单中删除这 1 笔采购订单。
最终,积压订单中有 (1000000000-3) 笔价格为 7 的销售订单,和 (999999995-1) 笔价格为 5 的采购订单。所以积压订单中的订单总数为 1999999991 ,等于 999999984 % (109 + 7) 。

 

提示:

  • 1 <= orders.length <= 105
  • orders[i].length == 3
  • 1 <= pricei, amounti <= 109
  • orderTypei 为 0 或 1

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/nu… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

  • 用优先队列,维护一个,价格由高到低排列的积压采购订单列表
  • 用优先队列,维护一个,价格由低到高排列的积压销售订单列表
  • 这样,在查找订单抵扣的时候,就能从前面遍历抵扣,因为最符合条件的订单都排在最前面
  • 这样遍历时候,如果遇到金额不符合当前订单的情况,就能提前跳出循环
  • 但性能还是过于拉跨,准备后序看下别的同学们的解答

代码

/**
 * @param {number[][]} orders
 * @return {number}
 */
var getNumberOfBacklogOrders = function(orders) {
   let buyList=[];//积压采购订单,按价格高到低排列
   let sellList=[];//积压销售订单,按价格低到高排列

    /**
 *订单处理,分流
 */
let orderActive=function(orders){
    orders.forEach((item)=>{
        if(item[2]===0){
           //采购订单
           for(let i=0;i<sellList.length;i++){
               if(sellList[i][0]<=item[0]){//积压订单按低到高排序的,所以如若发现订单金额不符合的情况了可以直接break
                 if(sellList[i][1]>item[1]){
                     //找到符合价格的订单,且当前笔订单数量大于所需要的数量
                     sellList[i][1]=sellList[i][1]-item[1];//抵扣掉积压销售订单数量
                     item[1]=0;//把还需要的采购订单数量归0

                 }else if(sellList[i][1]===item[1]){
                     //当前笔订单数量等于所需要的数量
                      sellList[i][1]=0;//删除整笔库存
                     item[1]=0;//把还需要的采购订单数量归0

                 }else if(sellList[i][1]<item[1]){
                     //当前笔订单数量小于所需要的数量
                      item[1]=item[1]-sellList[i][1];//把还需要的采购订单数量,抵扣掉进入下一个循环继续抵扣 
                        sellList[i][1]=0;//删除整笔库存
                        
                 }
                 if(item[1]===0) break;//订单处理完了,就结束循环

               }else{
                   break;//由于订单是按价格升序排列的,匹配到价格比要求价格高的就可以提前break了
               }
           }
      
        }else{
            //销售订单
            for(let i=0;i<buyList.length;i++){
               if(buyList[i][0]>=item[0]){//积压采购订单相反,是高到低排序的,所以如若发现订单金额不符合的情况了可以直接break
                 if(buyList[i][1]>item[1]){
                     //找到符合价格的订单,且当前笔订单数量大于所需要的数量
                     buyList[i][1]=buyList[i][1]-item[1];//抵扣掉积压采购订单数量
                     item[1]=0;//把还需要的销售订单数量归0

                 }else if(buyList[i][1]===item[1]){
                     //当前笔订单数量等于所需要的数量
                
                      buyList[i][1]=0;//删除整笔库存
                     item[1]=0;//把还需要的销售订单数量归0

                 }else if(buyList[i][1]<item[1]){
                     //当前笔订单数量小于所需要的数量
                       item[1]=item[1]-buyList[i][1];//先把销售订单数量,抵扣掉进入下一个循环继续抵扣   
                        buyList[i][1]=0;//删除整笔库存
                     
                 }
                 if(item[1]===0) break;//订单处理完了,就结束循环

               }else{
                   break;//由于订单是按价格高到低,匹配到价格比要求价格低的就可以提前break了
               }
           }
        }


      //抵扣完成,采购订单还有没抵扣完的,则执行积压处理
     if(item[1]>0)  add(item);
    })


}
/**
 *添加挤压订单
 */
let add=function(order){
    if(order[2]===0){
       //采购订单,降序排列,找到比自己低的,然后插入它前面
       for(let i=0;i<buyList.length;i++){
           if(buyList[i][0]<=order[0]){
              buyList.splice(i,0,order) ;
              return;
           }
       }
       buyList.push(order);//没找到就插入末尾
    }else{
        //销售订单,升序排列,找到比自己高的,然后插入它前面
       for(let i=0;i<sellList.length;i++){
           if(sellList[i][0]>=order[0]){
              sellList.splice(i,0,order) ;
              return;
           }
       }
       sellList.push(order);//没找到就插入末尾
    }
}

    orderActive(orders);
    let num=0;
    buyList.forEach((item)=>{
        num+=item[1];
    })
       sellList.forEach((item)=>{
        num+=item[1];
    })

    return num%(Math.pow(10,9)+7);

    

};