上半年打算跳槽的时候参加了美团的一次面试,面试中问到了一道美团业务中的算法题,当时没有反应过来,答得也不好。
大半年过去了,这期间一直时不时想起这道题,琢磨它的解法。最近在学习动态规划,有了一点新思路,记录一下。
这道题题目大意是这样的(时间太久记不起原话了):
美团外卖每天都会产生很多订单,外卖小哥基于订单进行配送,系统会标记小哥每个订单开始配送和结束配送的时间点。
求单日配送最高峰时的订单数量。
什么叫单日配送最高峰呢,就是当天同时在配送中的订单数量最高。
题目中的时间点都精确到秒,也就是在某一秒的时候小哥们同时配送了最多订单数,求这个订单数是多少。
当时被问的时候第一反应就是先用一个HashMap<Integer, Integer>记录个时间点的订单数,key是一天的时间点,一共24*60*60=86400个,value是该时间点在配送中的订单,然后遍历这个map找最大value。
但是这个解法有一个硬伤,遍历订单往map里设置值的时候成本很大。比如现在有一个订单,12:00开始配送,12:30结束配送,那么这三十分钟对应的1800秒在map里有1800个key,设置的时候这1800条数据都要改一轮,时间复杂度很高。
现在有个新思路,用动态规划的方式去解这个问题。很显然每秒在配送中的订单数跟上一秒的订单数是相关的,具体来说就是:
第i秒在配送中的订单数=前一秒的订单数 + 第i秒新开始的订单数 - 第i秒结束的订单数。
定义三个数组,start、end、orders,都是86400的长度
start[i]表示在一天的第i秒开始配送的订单数
end[i]表示在一天的第i秒结束配送的订单数
orders[i]表示在一天的第i秒在配送中的订单数
那么题目就是求orders数组中的最大项,并且:
orders[i] = orders[i - 1] + start[i] - end[i]
(其实面试官有直白的引导过我,问我上一秒的配送订单数和下一秒订单数之间有没有联系,唉T_T)
遍历输入的订单数据,设置好start和end数组,然后计算初始值orders[0],很显然order[0] = start[0](假设第一秒没有结束配送的订单,具体边界和初始值可以跟面试官确认)。
再依次计算出orders数组,计算的过程可以把最大值记录下来,这个最大值就是所求解。
分析这个解法,时间复杂度很简单O(n),空间复杂的也只用了常数空间,应该算是一个合格的解法了。