假设我有[开始,结束]形式的N个区间。我需要弄清楚这些间隔是否覆盖了整个范围。
例如:如果我的间隔是[4.5,5.765]和[5.8,10]且间隔是[5,10],那么如果间隔为[6,9.99]则应该报告相同数据的假值报告确实。
我需要1e-9的精度。间隔和范围将在[-1000,1000]。
这个问题在O(NlgN)时间内是否可以解决?其中N =间隔数。
答案 0 :(得分:2)
如果您对所有间隔(O(N * log N)
)的起点和终点进行排序,那么在O(N)
段中您可以跟踪:
-1000
和1000
之间的数字行上的当前位置,该位置依次获取任何时间间隔的每个开始/结束点。如果在此过程中的任何一点,当前值都在目标范围内,并且当前的间隔数为0,则间隔不会覆盖目标范围。如果在到达目标范围的末尾之前从未发生过,那么目标就会被覆盖。
由于时间间隔已关闭,请务必在值为r
的“起点”之前对值为r
的“终点”进行排序,以确保您返回如果时间间隔为[0,1]
且[1,2]
且目标为[0,2]
,则为“true”。
IEEE双精度对于+/- 1000范围内的粒度1e-9
已足够,但请注意5.8
无法在二进制浮点中精确表示的问题。因此,根据计算间隔的方式,计算或表示错误可能会引入微小的“间隙”。因此,您可能希望在开始之前进行某种舍入到最接近的十亿分之一,和/或使用基数为10而不是基数为2的相关值表示。
答案 1 :(得分:1)
虽然你已经得到了一些好的答案,但我认为我会做出简单而简单的贡献。
你没有告诉我们间隔是否可以重叠,所以我会假设他们可以。 (否则,简单的O(N)搜索过程将告诉您您的范围是否在其中一个区间内。)
如果多个范围的间隔设置保持不变,最好的办法是根据起点对预设间隔进行预先排序。 (这通常是O(N logN)操作,但您只需要执行一次)。然后,你可以这样做:
checkRange(range, intervals[])
for each ( intv in intervals )
if intv.start > range.start
return false
if intv.end >= range.end
return true
if intv.end > range.start
range.start = interval.end
return false
这只是一次O(N)传球。
如果每个范围的间隔集可以更改,那么以下递归算法可能会或者可能不会比每次排序间隔更好:
delta = 1e-9
checkRange(range, intervals[])
for each ( intv in intervals )
if intv.start <= range.start and intv.end >= range.end
return true
if intv.end < range.start or intv.start > range.end
continue
if intv.start < range.start and intv.end > range.start
range.start = interval.end
continue
if intv.start < range.end and intv.end > range.end
range.start = interval.end
continue
range1 = new range(start = range.start, end = intv.start - delta)
range2 = new range(start = intv.end + delta, end = range.end)
intervals = intervals after intv
return checkRange(range1, intervals) and checkRange(range2, intervals)
因为,对于数组或链表,您可以将intervals after intv
保留在与原始intervals[]
相同的内存空间中,这只是使用一些堆栈空间进行递归迭代而不是更多。至于计算复杂性,比我更好的人将不得不考虑证明它的内容,但我觉得它可能相当不错。
答案 2 :(得分:0)
您可以进行模糊排序。
最好的情况是O(n)
和平均情况O(n log n)
。这类似于快速排序。当所有间隔中存在至少一个点时,即最佳情况发生,即它们全部重叠。通常,重叠越多,算法与任何其他排序算法相比就越好。
以下是此算法的详细分析。 http://web.media.mit.edu/~dlanman/courses/cs157/HW3.pdf