Finding (number of) overlaps in a list of time ran

2020-02-02 10:05发布

Given a list of time ranges, I need to find the maximum number of overlaps.

Following is a dataset showing a 10 minute interval of calls, from which I am trying to find the maximum number of active lines in that interval. ie. from the example below, what is the maximum number of calls that were active at the same time:

CallStart   CallEnd
2:22:22 PM  2:22:33 PM
2:22:35 PM  2:22:42 PM
2:22:36 PM  2:22:43 PM
2:22:46 PM  2:22:54 PM
2:22:49 PM  2:27:21 PM
2:22:57 PM  2:23:03 PM
2:23:29 PM  2:23:40 PM
2:24:08 PM  2:24:14 PM
2:27:37 PM  2:39:14 PM
2:27:47 PM  2:27:55 PM
2:29:04 PM  2:29:26 PM
2:29:31 PM  2:29:43 PM
2:29:45 PM  2:30:10 PM

If anyone knows an alogrithm or can point me in the right direction, I would be grateful.

TIA,

Steve F

标签: algorithm
9条回答
手持菜刀,她持情操
2楼-- · 2020-02-02 10:30

Here is a working algorithm in Python

def maximumOverlap(calls):
    times = []
    for call in calls:
        startTime, endTime = call
        times.append((startTime, 'start'))
        times.append((endTime, 'end'))
    times = sorted(times)

    count = 0
    maxCount = 0
    for time in times:
        if time[1] == 'start':
            count += 1    # increment on arrival/start
        else:
            count -= 1    # decrement on departure/end
        maxCount = max(count, maxCount)  # maintain maximum
    return maxCount

calls = [
('2:22:22 PM', '2:22:33 PM'),
('2:22:35 PM', '2:22:42 PM'),
('2:22:36 PM', '2:22:43 PM'),
('2:22:46 PM', '2:22:54 PM'),
('2:22:49 PM', '2:27:21 PM'),
('2:22:57 PM', '2:23:03 PM'),
('2:23:29 PM', '2:23:40 PM'),
('2:24:08 PM', '2:24:14 PM'),
('2:27:37 PM', '2:39:14 PM'),
('2:27:47 PM', '2:27:55 PM'),
('2:29:04 PM', '2:29:26 PM'),
('2:29:31 PM', '2:29:43 PM'),
('2:29:45 PM', '2:30:10 PM'),
]
print(maximumOverlap(calls))
查看更多
看我几分像从前
3楼-- · 2020-02-02 10:35

Following must work:

  1. Sort all your time values and save Start or End state for each time value.
  2. Set numberOfCalls to 0 (count variable)
  3. Run through your time values and:

    • increment numberOfCalls if time value marked as Start
    • decrement numberOfCalls if time value marked as End
    • keep track of maximum value of numberOfCalls during the process (and time values when it occurs)

Complexity: O(n log(n)) for sorting, O(n) to run through all records

查看更多
SAY GOODBYE
4楼-- · 2020-02-02 10:39

I think an important element of good solution for this problem is to recognize that each end time is >= the call's start time and that the start times are ordered. So rather than thinking in terms of reading the whole list and sorting we only need to read in order of start time and merge from a min-heap of the end times. This also addresses the comment Sanjeev made about how ends should be processed before starts when they have the exact same time value by polling from the end time min-heap and choosing it when it's value is <= the next start time.

max_calls = 0
// A min-heap will typically do the least amount of sorting needed here.
// It's size tells us the # of currently active calls.
// Note that multiple keys with the same value must be supported.
end_times = new MinHeap()
for call in calls:
  end_times.add(call.end)
  while (end_times.min_key() <= call.start) {
    end_times.remove_min()
  }
  // Check size after calls have ended so that a start at the same time
  // doesn't count as an additional call.  
  // Also handles zero duration calls as not counting.
  if (end_times.size() > max_calls) max_calls = end_times.size()
}
查看更多
登录 后发表回答