我有一个可能重叠区间的端点列表,我想要一种有效的方法来计算k区间覆盖的总面积,k=1,2,...
(不进行所有成对比较)。或者,这不可能吗?
例如,假设x是起点列表,y是终点列表,
那x[i] < y[i]
和
x = (1.5, 2, 3, 5)
y = (3, 4, 4, 6)
使至少一个区间所覆盖的总面积为3.5,并且至少两个区域所覆盖的总面积为1.
谢谢,ph。
答案 0 :(得分:7)
这是来自计算几何的经典线扫描问题。
在每个起点放置+1,在每个终点放置-1。然后想象从负无穷大到正无穷大的数字线上行走。
每次遇到+1时,将身高增加1.每当你达到-1时,减少你的身高。当您在数字线上从p1移动到p2时,将p2 - p1(长度扫描)添加到给定高度所覆盖的数量。
然后,您将获得每个高度精确覆盖的长度直方图。如果要处理“至少两个间隔”的情况,可以累计总数。
答案 1 :(得分:1)
我不知道@rrenaud在写同样的东西时发布了他的解决方案,所以我会省略解释并给你代码。这是行扫描的javascript版本:
// x and y inputs are your start and end points for ranges,
// as in the example data
function countOverlapRanges(x, y) {
var ranges = [];
var n = x.length;
if (n !== y.length) {
throw "Input arrays must be the same length!";
}
var i;
// iterate over all inputs, pushing them into the array
for (i = 0; i < n; ++i) {
ranges.push({
value: x[i],
change: 1
});
ranges.push({
value: y[i],
change: -1
});
}
// sort the array into number-line order
ranges.sort(function (a, b) {
return a.value - b.value;
});
var result = {};
var k = 1;
var maxK = 1;
n = ranges.length;
// iterate over the sorted data, counting the size of ranges
var cur, value, lastValue = ranges[0].value;
for (i = 1; i < n; ++i) {
cur = ranges[i];
value = cur.value;
if (k) {
var difference = value - lastValue;
result[k] = (result[k] || 0) + difference;
}
k += cur.change;
maxK = Math.max(maxK, k);
lastValue = value;
}
// so far we've counted the ranges covered by exactly k intervals.
// adjust the results to get the size of ranges covered by
// at least k intervals.
var sum = 0;
for (i = maxK; i > 0; --i) {
sum = result[i] = sum + result[i];
}
return result;
}
它返回一个对象,它将k值映射到沿线的距离。