有重叠区间段中寻找最值 Pinterest面试题

来源:互联网 发布:php处理图片上传 编辑:程序博客网 时间:2024/06/05 18:54

题目源自于待字闺中的微信,是Pinterest公司的一道面试题。

题目:给如下的数据格式:

<start_time, end_time, value>
比如有一组数据:
1, 3, 100
2, 4, 200
5, 6, 300
……

这些数据时间区间可能有重合的部分。比如在时间段2~3之间,value的和是100+200 = 300.。

要求找出这组数据中最高的value和。


思路:

     不好的做法:看到题目中的时间都是整数值,即把时间看做离散值,一个思路是做一个把所有时间点建成一个数组,然后给所有时间点做计数统计。所需要的空间复杂度是O(k),并且k和输入数据中的时间范围有关,并且还需要计算时间范围。所需要的时间复杂度是O(n*n),因为对每一条数据都要循环做一次计数。并且,如果输入数据中的时间有小数(或者说时间值不是离散的),那么这个做法就失效了。

    改进思路:上一个思路因为不能处理连续的时间值数据。想到使用链表来记录时间段的value总值,链表按时间排序,并且链表每个结点的时间区间不重叠。每当录入一条输入数据,检查这条数据的时间区间。如果是全新的时间区间,就新建一个新的结点插入到对应的位置;如果需要切割原链表时间区间,则修改原链表中对应的结点的区间,并新建一个结点插入到对应位置;如果这条数据的时间区间已经全部在链表中覆盖有,则将相应结点的value值更新一下。这个过程,过于复杂了!

    优化思路:上一个思路太复杂了,换一个思路,海阔天空。过程化的思想,栈的思想。将一个时间区间A看作一组动作,进入A看做入栈,离开A看做出栈。那么在整个时间轴上从左到右,伴随着若干个出入栈动作,入栈动作对应value的增加,出栈动作对应value的减小。栈中的总值就是当前时间处的value总值,其不断更新。题目要寻找的,就是在value总值在更新过程中的最大值。


优化思路的解法:

    1、先将输入数据拆分为入、出两个动作,记作(time, val)。入的时间就是start_time,入的动作是加上value值;出的时间就是end_time,出的动作是加上-value值。需要O(n)时间。

   2、将所有的出入动作依据时间做一个排序,需要O(logn)时间。

   3、设定一个value总值和max:对有序的入出动作做线性扫描,并实时更新value值和max值。最终将得到所寻找的max值。


代码:时间复杂度为O(logn + n),空间复杂度为O(n)。

void find_max(vector<vector<int> > input){int n = input.size();int i;vector<int> onedata;vector<vector<int> > data;for(i=0;i<n;i++){onedata.clear();onedata.push_back(input[i][0]);onedata.push_back(input[i][2]);data.push_back(onedata);onedata.clear();onedata.push_back(input[i][1]);onedata.push_back(-input[i][2]);data.push_back(onedata);}sort(data.begin(), data.end());int sum = 0;int max = data[0][1];for(i=0;i<2*n;i++){sum += data[i][1];if(sum > max)max = sum;}return max;} //代码我是大致写的,并没有完整编译测试


一个好的思路,真的可以使得问题解决简化很多。




0 0