假设我有一个 n 积分区间[a,b]的列表,每个区间代表集合S = {a,a + 1,... b}。重叠定义为| S_1 \ cap S_2 |。示例:[3,6]和[5,9]在[5,6]上重叠,因此其长度为2.任务是使用Just-O(n ^ 2)找到两个间隔最长的区间递归和不动态编程。
天真的方法显然是蛮力的,它不具备时间复杂性条件。尝试扫描线算法和/或最长公共子序列算法时,我也没有成功。我找不到将其划分为子问题的方法。任何想法都将不胜感激。
还发现了这一点,在我看来根本不起作用:
答案 0 :(得分:1)
这是一种花费N log(N)
时间的方法。
将每个间隔[a,b] [c,d]
细分为一对数组,如下所示:
pair<a,-1>
pair<b,a>
pair<c,-1>
pair<d,c>
sort these pairs in increasing order. Since interval starts are marked as -1, in case of ties interval they should come ahead of interval ends.
for i = 0 to end of the pair array
if current pair represents interval start
put it in a multiset
else
remove the interval start corresponding to this interval end from the multiset.
if the multiset is not empty
update the maxOverlap with (current_interval_end - max(minimum_value_in_multiset,start_value_of_current_interval)+1)
此方法应将maxOverlap
更新为可能的最高值。
答案 1 :(得分:0)
保留有关两个最大重叠间隔max1
和max2
的信息(开头为空)。
将输入列表[x1, y1] .. [xn, yn]
= I1..In
按值x
排序,如果遇到相等则丢弃两个间隔中较短的一个。在推出时间间隔时,请更新max1
和max2
。
对于每个间隔,在线性时间中添加属性max
,显示所有前面间隔的最大y
值(在排序列表中):
rollmax = −∞
for j = 1..n do
Ij.max = rollmax
rollmax = max(rollmax, Ij.y)
在已排序,已过滤和扩展的输入列表上,执行以下查询。它使用一个不断扩展的区间子列表,其间隔小于当前搜索的区间Ii
,作为递归函数SearchOverlap
的输入。
for i = 2..n do
SearchOverlap(Ii, 1, i − 1)
return {max1, max2}
函数SearchOverlap
使用divide and conquer
方法遍历排序列表Il, .. Ir
。它将这样的列表想象成一个完整的二叉树,其间隔为Ic
作为其本地根。测试Ic.max < I.max
用于始终决定以与I
最大重叠的间隔方向遍历二叉树(左/右)。请注意,I
是查询间隔,与log(n)
个其他间隔进行比较。另请注意,可能在此类遍历中传递最大可能的重叠间隔,因此检查函数SearchOverlap
开头的最大重叠。
SearchOverlap(I , l, r)
c = ceil(Avg(l, r)) // Central element of queried list
if Overlap(max1, max2) < Overlap(I , Ic) then
max1 = I
max2 = Ic
if l ≥ r then
return
if Ic.max < I.max then
SearchOverlap(I , c + 1, r)
else
SearchOverlap(I , l, c − 1)
return
最后返回最大的重叠间隔(如果不为空)。总复杂度为O(n log(n))
。