Algorithm 确定给定一组N个间隔是否覆盖了整个范围
假设我有N个形式为[开始,结束]的区间。我需要找出这些间隔是否覆盖了整个范围 例如:如果我的区间为[4.5,5.765]和[5.8,10],区间为[5,10],则应报告为假,而对于相同的数据,如果区间为[6,9.99],则应报告为真 我需要1e-9的精度,间隔和范围将在[-10001000]内Algorithm 确定给定一组N个间隔是否覆盖了整个范围,algorithm,range,Algorithm,Range,假设我有N个形式为[开始,结束]的区间。我需要找出这些间隔是否覆盖了整个范围 例如:如果我的区间为[4.5,5.765]和[5.8,10],区间为[5,10],则应报告为假,而对于相同的数据,如果区间为[6,9.99],则应报告为真 我需要1e-9的精度,间隔和范围将在[-10001000]内 这个问题在O(NlgN)时间内可以解决吗??其中N=间隔数。如果对所有间隔的起点和终点进行排序(O(N*logn)),则在O(N)过程中,您可以跟踪: 编号线上-1000和1000之间的当前位置,依次取
这个问题在O(NlgN)时间内可以解决吗??其中N=间隔数。如果对所有间隔的起点和终点进行排序(
O(N*logn)
),则在O(N)
过程中,您可以跟踪:
- 编号线上
和-1000
之间的当前位置,依次取任意间隔的每个起点/终点1000
- 有多少间隔“当前”打开,即有多少间隔在编号线上的该点相交
r
的“起点”之前排序值为r
的“终点”,以确保在间隔为[0,1]
和[1,2]
且目标为[0,2]
的情况下返回“true”
IEEE双精度对于+/-1000范围内的粒度
1e-9
是足够的,但是请注意5.8
不能用二进制浮点精确表示的问题。因此,根据计算时间间隔的方式,可能存在由计算或表示错误引入的微小“间隙”。因此,您可能希望在开始之前进行某种形式的四舍五入到最接近的十亿分之一,和/或使用以10为基数而不是以2为基数表示所涉及的值。虽然您已经得到了一些很好的答案,但我想我应该提供一些简单明了的东西
你没有告诉我们间隔是否可以重叠,所以我假设它们可以重叠。(否则,简单的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)
delta=1e-9
检查范围(范围、间隔[])
对于每个(intv间隔)
如果intv.start=range.end
返回真值
如果intv.endrange.end
持续
如果intv.startrange.start
range.start=interval.end
持续
如果intv.startrange.end
range.start=interval.end
持续
范围1=新范围(开始=范围.start,结束=intv.start-增量)
范围2=新范围(开始=intv.end+增量,结束=范围.end)
间隔=intv后的间隔
返回检查范围(范围1,间隔)和检查范围(范围2,间隔)
因为,对于数组或链表,可以将intv之后的
间隔保持在与原始间隔[]
相同的内存空间中,这只会为递归迭代使用一些堆栈空间,仅此而已。至于计算复杂性,比我更好的人将不得不研究如何证明它,但我觉得它可能相当不错。你可以做模糊排序。
最佳情况是O(n)
和平均情况O(n log n)
。这类似于快速排序。最佳情况发生在所有间隔中至少存在一个点时,即它们都重叠。一般来说,重叠越多,该算法优于任何其他排序算法
下面是对该算法的详细分析 间隔是否预先排序?您关心空间限制吗?不。间隔不是预先排序的。但它保证间隔将在[-10001000]范围内。很抱歉,现在我已经更新了。我有256MB的空间,但我认为这并不重要。您是否正在考虑存储每个值。呵呵!!所以理论上你可以创建一个位集,它是[-1000*1e9,1000*1e9],并在运行时屏蔽位。这在间隔数量上是线性的,但取决于总范围和每个间隔的范围。不幸的是,这会占用相当多的空间…我认为如果我有整数值,使用位掩码会更合适,或者精度会低得多。这占用了很多空间。有没有更好的算法。我听说过区间树,但我不确定它是否能完成这项任务。你可以假设NJust有趣的事情:排序后,我相信你可以使用不相交集来得到所有的闭合区间。