我最近在Tardos和Kleinberg的Algorithm Design第4章中读到了Interval Scheduling算法。提供给区间调度问题的解决方案是:
Sort the n intervals based on their finishing time and store in array F
A = [] #list of intervals
S = array with property that S[i] contains the finishing time of the ith interval
i = 0
For j = 0 to n-1
if S[j] >= F[i] #this interval does not overlap with the ith interval
i = j
A.add(j)
可以在此处找到C ++ / Java / Python中的此算法:http://www.geeksforgeeks.org/greedy-algorithms-set-1-activity-selection-problem/
问题的扩展,也称为间隔着色问题,可以解释如下。
我们给出了一组间隔,我们想要为所有间隔着色 因此,给定相同颜色的间隔不会与目标相交 是尽量减少使用的颜色数量。
书中提出的算法是:
Sort the intervals by their start times in a list I
n = len(I)
For j = 1 to n:
For each interval I[i] that precedes I[j] and overlaps it:
Exclude the label of I[i] from consideration for I[j]
The jth interval is assigned a nonexcluded label
然而,这个算法的运行时间是不是O(n ^ 2)?我想到了一个更好的,但我不确定它是否正确。基本上,我们修改了Interval Scheduling的算法。
Sort the n intervals based on their finishing time and store in array F
A = []
x = 1
S = array with property that S[i] contains the finishing time of the ith interval
i = 0
while F is not empty:
new = []
For j = 0 to n-1
if S[j] >= F[i] #this interval does not overlap with the ith interval
i = j
A.add(F[j])
else:
new.add(F[j])
F = new
Recompute S
print x, A
A = []
x++
我可能在伪代码中有一个愚蠢的错误,但我希望你理解我的算法尝试做什么。基本上我通过重复运行标准间隔调度算法来剥离所有可能的颜色。
那么,我的算法不应该打印所有间隔的各种颜色吗?如果它是一个正确的算法,这比以前的算法更有效吗?如果不是,请你提供反例? 谢谢! (有关区间调度的更多信息,请访问:https://en.wikipedia.org/wiki/Interval_scheduling)
答案 0 :(得分:1)
您的算法可以产生次优的解决方案。以下是您的算法将产生的示例:
--- -----
----
------------
显然,对于相同的输入,可以使用以下双色解决方案(将由经过验证的最佳算法生成):
--- ------------
---- -----
最后,尽管本书提出的算法的伪代码描述看起来确实需要O(n ^ 2)时间,但可以使用其他数据结构加速。这是一个O(n log n)算法:不是循环遍历所有n个区间,而是按递增顺序循环遍历所有2n区间端点。保持按颜色排序的可用颜色的堆(优先级队列),最初包含n种颜色;每当我们看到间隔起始点时,从堆中提取最小的颜色并将其分配给该间隔;每次我们看到间隔终点时,将其指定的颜色重新插入堆中。处理的每个端点(开始或结束)都是O(log n)时间,其中有2n个。这与排序间隔的时间复杂度相匹配,因此总体时间复杂度也是O(n log n)。