我遇到了一个算法难题如下:
给出一系列事件(名称,开始时间,结束时间) e.g。
(a,1,6) (b,2,4) (c,7,8) ...
事件根据其开始时间排序。我被要求将事件转换为另一种形式(名称,时间),
e.g。 (a,1) (b,2) (b,4) (a,6) (c,7) (c,8)
请注意,每个事件现在都分为两个事件,并且需要按时间排序。
最天真的方式是O(n log n),我想到了其他几种方法,但不是它们比O(n log n)快。
有谁知道解决这个问题的最有时间和空间效率的方法?
答案 0 :(得分:2)
从头到尾扫描时间,保持活动事件结束时间的优先级队列,其顶部元素重复比较到下一个事件的开始时间。这是O(n log k),其中k是同时事件的最大数量,在输入和输出的顶部有额外的空间使用O(k)。我用C ++实现了类似的答案:https://stackoverflow.com/a/25694591/2144669。
答案 1 :(得分:1)
这可以证明与常规排序一样耗时。
例如,假设我要对N个正数进行排序。我可以将其转换为排序形式(a1,0,num1),(a2,0,num2),...,(aN,0,numN)的N个元组的问题。这将产生排序结果(a1,0),(a2,0),...,(aN,0),(aSorted1,numSorted1),...,(aSortedN,numSortedN)。因此我们得到{numSorted1,...,numSortedN}。事实证明,最后一种类型应该至少采用O(N * Log(N)),因此在一般情况下你不能得到更好的。
但是,如果您说开始时间是唯一的,则可能会对问题进行一些其他优化。
编辑:我们在这里使用额外的O(N)空间,但我认为可以在这种情况下进行争论。然而,它并不是一个严谨的答案。
答案 2 :(得分:0)
真正有效的实施取决于应用于您的数据的某些限制。 但是,通常,以下方法可以对列表中的O(N)和内存2N进行排序:
1. Create struct like:
struct data {
int timestamp; // Event timestamp
int orig_index; // Index of original event in the input array
}
2. Copy data from the input array into array of structures [1].
Each original event is copied into two structs "data". This is O(N).
3. Sort resulting array with RadixSort, by field "timestamp".
This is again O(N): http://en.wikipedia.org/wiki/Radix_sort
4. Create output array, and restore names from original array by
index "orig_index", if needed. Again O(N).
答案 3 :(得分:0)
没有算法的时间效率更高,因为具有omega(nlogn)紧密下限的排序问题可以简化为这个问题(对数组进行排序,选择任何一组启动时间等) 至于空间复杂度,Heapsort使用O(1)辅助空间和O(nlogn)时间,可能是最好的最坏情况算法。