身份的可用范围的数字,当两个数字范围是重叠

问题描述:

如果我有一个现有的范围:身份的可用范围的数字,当两个数字范围是重叠

1-10 
11-50 

然后,我将进入1新的范围 - 60,我怎么能检测到新的范围是添加重叠到以前的条目?我怎样才能获得可用范围?在这种情况下,可用范围是51-60。

有没有人在这里有这个好主意?

感谢您的帮助。

这里是我当前的代码:

$saved = array(
          array(
            "start" => 1, 
            "end" => 10 
           ), 
          array(
            "start" => 10, 
            "end" => 50 
          ) 
         ); 
      $new_range = array(
           "start" => 1, 
           "end" => 60 
          ); 
      $usable_range = array(); 
      $previous_from = 0; 
      $previous_to = 0; 
      foreach($saved as $value) 
      { 
       $range_start = 0; 
       $range_end = 0; 
       if($previous_from<$value['start']) 
       { 
        $previous_from = $value['start']; 
       } 
       if($previous_to<$value['end']) 
       { 
        $previous_to = $value['end']; 
       } 
       if($previous_from<=$new_range['start']) 
       { 
        if($previous_to<$new_range['end']) 
        { 
         $range_start = $previous_to+1; 
         $range_end = $new_range['end']; 
         $new_range['start'] = $range_start; 
        } 
       } 
       else if($previous_from>=$new_range['start']) 
       { 
        if($previous_to<$new_range['end']) 
        { 
         $range_start = $previous_to+1; 
         $range_end = $new_range['end']; 
         $new_range['start'] = $range_start; 
        } 
       } 
       $usable[] =  array("range_start"=>$range_start,"range_end"=>$range_end);    
      } 
+0

我已经手动尝试过,但它是有效的。当范围很大时,输出不正确。 – 2013-05-09 03:26:09

+0

你能告诉我你试过的东西吗? – John 2013-05-09 03:27:21

+0

你现在怎么研究范围? – andrewsi 2013-05-09 03:28:30

通话每间隔(最小值,最大值)

1)通过其min排序的时间间隔的列表。

2)检查是否有任何max大于min的下一个条目。如果是,则创建其分钟中较小的间隔和其最大值中较大的一个间隔,然后将其添加到列表中以代替这两个间隔。

3)每当你得到一个新的时间间隔,二进制搜索到列表添加它,按min排序。然后,使用与2)中类似的逻辑,尝试将它与下面的条目和上面的条目合并,直到不再有可能的合并为止。


编辑:几个变化。

首先,由于我们使用整数而不是浮点数,所以如果您有一个像1,10和11,20那样的间隔,那么10和11之间就没有'间隙' - 所以我们应该认为这是一个更大的间隔1,20。反映此,而不是检查,看看是否max > next min,如果max >= next min - 1

第二,如果你想找到合并一个新的区间到您的间隔名单时,通过重叠形成的所有间隔:

1)由于您的间隔列表被称为是在它被排序的状态min,并且还按max排序,进行二分搜索以找到刚刚在新分钟上方的最小分钟和刚刚在新的最大分钟上方的最大最大值。

2)遍历数组中的最小值,最大值,最小值,最大值等等,它们位于新分钟和新最大值之间。在最低分之下,高于最高最高以及在每个最高/最低之间,您可以计算在那里的'间隙'中的间隔,然后在例如数组。


例如,如果您的间隔列表包含13,16,21,24和31,38,你要计算新的间隔1,30的非重叠:

1)我们二进制搜索到我们的名单,发现13高于1和24的最低分高于30

2)最大的最大迭代,我们像这样:

  • 我们分和最低分之间是1和13 - 所以这形成了一个时间间隔1,12 (包括底部,顶部)。添加到返回数组。
  • 在最大值和下一个最小值之间是16和21 - 所以这形成了一个区间17,20(两端都是唯一的)。添加到返回数组。
  • 在max和我们的最大值之间是24和30--所以这形成了一个间隔25,30(独占底部,包含顶部)。添加到返回数组。
+0

感谢Patashu,我在步骤2中不太明白。可以用数学方式或实际方式显示它。我喜欢这个想法。 – 2013-05-09 03:52:16

+1

@John Rey Flores如果你有一个间隔(mina,maxa)和一个间隔(minb,maxb),它们会重叠,如果maxa> minb或mina> maxb(如果你已经按min分类,你只需要麻烦检查一个其中,因为其他永远不会是真的)。如果它们重叠,则跨越a和b全部的间隔由min(mina,minb),max(maxa,maxb)组成。例如如果你有1,3和2,4,它们重叠,因为3> 2和min(1,2),max(3,4)是1,4。合理? – Patashu 2013-05-09 03:54:42

+0

是的,它是有道理的,如果我有一个数字1,10和11,50和1,60,我怎么能计算出只有51到60不重叠?这个问题清楚吗? – 2013-05-09 04:01:09

查找重叠可以描述为查找交集。同样,找到可用范围可以被描述为找到差异。这样做的一种方法是将这些集合视为数组并使用array_intersect [1]和array_diff [2]函数。

这就是我能想出的所有细节。

[1] - http://php.net/manual/en/function.array-intersect.php

[2] - http://www.php.net/manual/en/function.array-diff.php

+0

如果间隔时间是“浮动”呢? – Patashu 2013-05-09 03:36:26

+0

OP在我第一次回复时没有发布任何代码示例,但我仍然认为我的回答可以解决问题。我从集合论的方法来看它。这些集合中的内容真的没有关系。看到这些集合确实包含数字,但是一定范围内的数据当然可以迭代以填充数组。一旦数组被填充,可以使用array_intersect和array_diff函数。 – cogsmos 2013-05-09 04:18:22

+0

区间算法!=设置算术。如果间隔是离散的,你可以假装使用集算术进行间隔算术,并用它们中的每个值填充它们,但这是一个缓慢的黑客攻击。 – Patashu 2013-05-09 04:20:08