Javascript 如何找到所有重叠的范围并将其划分为块?
我有一个范围数组,我希望能够找到所有重叠的范围: 例如:Javascript 如何找到所有重叠的范围并将其划分为块?,javascript,algorithm,Javascript,Algorithm,我有一个范围数组,我希望能够找到所有重叠的范围: 例如: 范围2与范围4重叠 范围3与范围4重叠 尽管范围2与范围3不重叠,因为它们都与范围4重叠。他们将被分为同一组 范围1和范围5仅相互重叠,因此它们将属于各自的组 请点击此处: 这里有一个简单的扫描算法。由于需要对范围进行排序,因此它以O(n log n)的形式执行 基本思想是从左向右扫描,查找起点和终点(这需要每个起点和终点的排序列表)。扫描时,请跟踪活动范围的数量(即,已遇到其起点但尚未遇到其终点的范围)。每次到达起点时,都需要将范围添加
这里有一个简单的扫描算法。由于需要对范围进行排序,因此它以O(n log n)的形式执行 基本思想是从左向右扫描,查找起点和终点(这需要每个起点和终点的排序列表)。扫描时,请跟踪活动范围的数量(即,已遇到其起点但尚未遇到其终点的范围)。每次到达起点时,都需要将范围添加到当前组中。范围计数通过在每个起点递增,在每个终点递减来维持。每次计数返回到0时,都会找到一个完整的组 如果要计算简化的范围集而不是组,可以简化。与在组中保留一组范围不同,当前合成组的起点在活动范围计数从0增加到1时设置,终点在活动范围计数从1减少到0时设置。在这种情况下,您只需要一个已排序的起点列表和一个已排序的终点列表(在所介绍的算法中,排序的起点是通过按起点对范围本身进行排序来找到的。需要该组,以便将范围添加到累计组中。)
- 将范围[当前范围]添加到当前范围组,增加当前范围和增加活动范围计数
- 循环
- 减少活动范围计数并增加当前结束
- 如果活动\u范围\u计数为0,则当前\u组已完成;保存它,并将当前_组重新初始化为空集
- 循环
/* Partition an array of ranges into non-overlapping groups */
/* Side-effect: sorts the array */
function partition(ranges) {
var end_values = ranges.map(function(r){return r.end}).sort(function(a, b){return a - b})
ranges.sort(function(a, b){return a.start - b.start})
var i = 0, j = 0, n = ranges.length, active = 0
var groups = [], cur = []
while (1) {
if (i < n && ranges[i].start < end_values[j]) {
cur.push(ranges[i++])
++active
} else if (j < n) {
++j
if (--active == 0) {
groups.push(cur)
cur = []
}
} else break
}
return groups
}
/* Given a array of possibly overlapping ranges, produces
* an array of non-overlapping ranges covering the same
* values.
*/
function compose_ranges(ranges) {
var starts = ranges.map(function(r){return r.start}).sort(function(a, b){return a - b})
var ends = ranges.map(function(r){return r.end}).sort(function(a, b){return a - b})
var i = 0, j = 0, n = ranges.length, active = 0
var combined = []
while (1) {
if (i < n && starts[i] < ends[j]) {
if (active++ == 0) combined.push({start: starts[i]})
++i
} else if (j < n) {
if (--active == 0) combined[combined.length - 1].end = ends[j]
++j
} else break;
}
return combined
}
/*将范围数组划分为不重叠的组*/
/*副作用:对数组进行排序*/
功能分区(范围){
var end_values=ranges.map(函数(r){return r.end}).sort(函数(a,b){return a-b})
排序(函数(a,b){返回a.start-b.start})
变量i=0,j=0,n=ranges.length,active=0
变量组=[],cur=[]
而(1){
如果(i
以下是我的看法:
var示例=[
{开始:17,结束:20},
{开始:9,结束:10.50},
{开始:15,结束:17},
{开始:11,结束:12},
{开始:18,结束:19.5},
{开始:19.5,结束:22},
{开始:11.5,结束:12.5},
{开始:11.5,结束:13},
{开始:17.5,结束:18.5},
{开始:19,结束:19.5},
{开始:22,结束:25}
]
函数分区重叠范围(数组){
array.sort(函数(a,b){
如果(a.启动b.开始)
返回1;
返回0;
});
var getMaxEnd=函数(数组){
if(array.length==0)返回false;
array.sort(函数(a,b){
如果(a.endb.end)
返回-1;
返回0;
});
返回数组[0]。结束;
};
var-rarray=[];
var g=0;
rarray[g]=[array[0]];
对于(变量i=1,l=array.length;i=array[i-1].start)
&&
(数组[i]。开始概念很简单:记录每个特定组的最大范围
试一试下面的代码
function contains(range, number) {
return number > range.start && number < range.end
}
function partitionIntoOverlappingRanges(array) {
var groups = [];
for (var i = 0; i < array.length; i++) {
for (var j = 0; j < groups.length; j++) {
if (contains(groups[j], array[i].start) || contains(groups[j], array[i].end)) {
groups[j].arrays.push(array[i]);
if (groups[j].start > array[i].start) groups[j].start = array[i].start;
if (groups[j].end < array[i].end) groups[j].end = array[i].end;
break;
}
}
if (j == groups.length) {
groups.push({
start: array[i].start,
end: array[i].end,
arrays: [array[i]]
})
}
}
return groups
}
函数包含(范围、编号){
返回编号>range.start&&number数组[i]。开始)组[j]。开始=数组[i]。开始;
如果(组[j]。结束<数组[i]。结束)组[j]。结束=数组[i]。结束;
打破
}
}
if(j==组长度){
推({
开始:数组[i]。开始,
结束:数组[i]。结束,
数组:[数组[i]]
})
}
var examples = [
{start: 17, end: 20},
{start: 9, end: 10.50},
{start: 15, end: 17},
{start: 11, end: 12},
{start: 18, end: 19.5},
{start: 19.5, end: 22},
{start: 11.5, end: 12.5},
{start: 11.5, end: 13},
{start: 17.5, end: 18.5},
{start: 19, end: 19.5},
{start: 22, end: 25}
]
function partitionIntoOverlappingRanges(array) {
array.sort(function (a,b) {
if (a.start < b.start)
return -1;
if (a.start > b.start)
return 1;
return 0;
});
var getMaxEnd = function(array) {
if (array.length==0) return false;
array.sort(function (a,b) {
if (a.end < b.end)
return 1;
if (a.end > b.end)
return -1;
return 0;
});
return array[0].end;
};
var rarray=[];
var g=0;
rarray[g]=[array[0]];
for (var i=1,l=array.length;i<l;i++) {
if ( (array[i].start>=array[i-1].start)
&&
(array[i].start<getMaxEnd(rarray[g]))
) {
rarray[g].push(array[i]);
} else {
g++;
rarray[g]=[array[i]];
}
}
return rarray;
} // end partitionIntoOverlappingRanges
function contains(range, number) {
return number > range.start && number < range.end
}
function partitionIntoOverlappingRanges(array) {
var groups = [];
for (var i = 0; i < array.length; i++) {
for (var j = 0; j < groups.length; j++) {
if (contains(groups[j], array[i].start) || contains(groups[j], array[i].end)) {
groups[j].arrays.push(array[i]);
if (groups[j].start > array[i].start) groups[j].start = array[i].start;
if (groups[j].end < array[i].end) groups[j].end = array[i].end;
break;
}
}
if (j == groups.length) {
groups.push({
start: array[i].start,
end: array[i].end,
arrays: [array[i]]
})
}
}
return groups
}