Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/443.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何找到所有重叠的范围并将其划分为块?_Javascript_Algorithm - Fatal编程技术网

Javascript 如何找到所有重叠的范围并将其划分为块?

Javascript 如何找到所有重叠的范围并将其划分为块?,javascript,algorithm,Javascript,Algorithm,我有一个范围数组,我希望能够找到所有重叠的范围: 例如: 范围2与范围4重叠 范围3与范围4重叠 尽管范围2与范围3不重叠,因为它们都与范围4重叠。他们将被分为同一组 范围1和范围5仅相互重叠,因此它们将属于各自的组 请点击此处: 这里有一个简单的扫描算法。由于需要对范围进行排序,因此它以O(n log n)的形式执行 基本思想是从左向右扫描,查找起点和终点(这需要每个起点和终点的排序列表)。扫描时,请跟踪活动范围的数量(即,已遇到其起点但尚未遇到其终点的范围)。每次到达起点时,都需要将范围添加

我有一个范围数组,我希望能够找到所有重叠的范围:

例如:
  • 范围2与范围4重叠
  • 范围3与范围4重叠
  • 尽管范围2与范围3不重叠,因为它们都与范围4重叠。他们将被分为同一组
  • 范围1和范围5仅相互重叠,因此它们将属于各自的组
  • 请点击此处:
    这里有一个简单的扫描算法。由于需要对范围进行排序,因此它以O(n log n)的形式执行

    基本思想是从左向右扫描,查找起点和终点(这需要每个起点和终点的排序列表)。扫描时,请跟踪活动范围的数量(即,已遇到其起点但尚未遇到其终点的范围)。每次到达起点时,都需要将范围添加到当前组中。范围计数通过在每个起点递增,在每个终点递减来维持。每次计数返回到0时,都会找到一个完整的组

    如果要计算简化的范围集而不是组,可以简化。与在组中保留一组范围不同,当前合成组的起点在活动范围计数从0增加到1时设置,终点在活动范围计数从1减少到0时设置。在这种情况下,您只需要一个已排序的起点列表和一个已排序的终点列表(在所介绍的算法中,排序的起点是通过按起点对范围本身进行排序来找到的。需要该组,以便将范围添加到累计组中。)

  • 按其起始值对范围进行排序

  • 列一个结束值列表,并对其排序(不必知道哪个范围属于端点)。称之为结束值

  • 将当前\u组初始化为空集,将活动\u范围\u计数初始化为0。将当前_范围和当前_结束初始化为0

  • 循环直到完成:

  • 如果当前\u范围是范围和范围的有效索引[current\u range]。开始值小于结束值[current\u end]:

    • 将范围[当前范围]添加到当前范围组,增加当前范围和增加活动范围计数
    • 循环
  • 否则,如果当前_end是end_值的有效索引:

    • 减少活动范围计数并增加当前结束
    • 如果活动\u范围\u计数为0,则当前\u组已完成;保存它,并将当前_组重新初始化为空集
    • 循环
  • 否则,请完成

  • 以下是两个javascript版本:

    /* 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
    }