Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/273.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/12.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
Php 涵盖输入日期范围内所有日期的日期范围组合_Php_Algorithm - Fatal编程技术网

Php 涵盖输入日期范围内所有日期的日期范围组合

Php 涵盖输入日期范围内所有日期的日期范围组合,php,algorithm,Php,Algorithm,我想找到与输入日期范围重叠的所有可能的日期范围组合。例如,如果用户输入2013/01/10至2013/01/25,我有以下日期范围: 2013/01/08 to 2013/01/10 2013/01/09 to 2013/01/15 2013/01/10 to 2013/01/20 2013/01/18 to 2013/01/27 2013/01/14 to 2013/01/19 2013/01/19 to 2013/01/25 2013/01/14 to 2013/01/26 2013/01/

我想找到与输入日期范围重叠的所有可能的日期范围组合。例如,如果用户输入2013/01/10至2013/01/25,我有以下日期范围:

2013/01/08 to 2013/01/10
2013/01/09 to 2013/01/15
2013/01/10 to 2013/01/20
2013/01/18 to 2013/01/27
2013/01/14 to 2013/01/19
2013/01/19 to 2013/01/25
2013/01/14 to 2013/01/26
2013/01/10 to 2013/01/26
我想找出与输入日期(2013/01/10至2013/01/25)重叠的上述日期的所有可能组合

与输入日期重叠的日期范围有两个示例:

{2013/01/09 to 2013/01/15, 2013/01/14 to 2013/01/26}
{2013/01/09 to 2013/01/15, 2013/01/14 to 2013/01/19, 2013/01/19 to 2013/01/25}
我没有列出与输入日期范围重叠的所有可能的日期范围
我想找到涵盖输入日期范围内所有日期的日期范围组合!,如果你看两个例子,我将日期范围合并为涵盖输入日期的所有日期
我不想检查输入日期范围为2的一个日期,如果日期范围包括输入日期的所有日期,或者是否!,我想组合日期范围,以查找所有可能的日期范围组合,这些组合涵盖输入日期范围的所有日期。
我想要一个算法来找到所有可能的日期组合,覆盖输入日期范围内的所有日期。
有什么快速算法可以解决这个问题吗?

我又添加了几个数据项,使它更有趣:

$start = strtotime('2013/01/10');
$end = strtotime('2013/01/25');
$range[0]['start'] = "2013/01/08";
$range[0]['end'] = "2013/01/10";
$range[1]['start'] = "2013/01/09";
$range[1]['end'] = "2013/01/15";
$range[2]['start'] = "2013/01/10";
$range[2]['end'] = "2013/01/20";
$range[3]['start'] = "2013/01/18";
$range[3]['end'] = "2013/01/27";
$range[4]['start'] = "2013/01/14";
$range[4]['end'] = "2013/01/19";
$range[5]['start'] = "2013/01/19";
$range[5]['end'] = "2013/01/25";
$range[6]['start'] = "2013/01/14";
$range[6]['end'] = "2013/01/26";
$range[7]['start'] = "2013/01/10";
$range[7]['end'] = "2013/01/26";
$range[8]['start'] = "2013/01/9";
$range[8]['end'] = "2013/01/15";
$range[9]['start'] = "2013/01/13";
$range[9]['end'] = "2013/01/19";
$heads = array();
$tails = array();
$combos = array();
$h = 0;
foreach ($range as $key => $value){
    $r1 = strtotime($value['start']);
    $r2 = strtotime($value['end']);
    if ($r1 <= $start && $r2 >= $end){
        $combos[] = $key;
    } elseif($r1 <= $start && $r2 > $start) {
        $heads[$h]['r1'] = $r1;
        $heads[$h]['r2'] = $r2;
        $heads[$h]['seq'] = $key;
        $h++;
    } elseif($r1 > $start && $r1 < $end && $r1 < $r2) {
        $tails[$key]['r1'] = $r1;
        $tails[$key]['r2'] = $r2;
        $tails[$key]['seq'] = $key;
    }
}
while (count($tails) > 0){
    $heads2 = array();
    $tails2 = array();
    $h2 = 0;
    foreach ($heads as $key1 => $value1){
        foreach ($tails as $key2 => $value2){
            if (($value1['r1'] < $value2['r1']) && ($value1['r2'] >= $value2['r1']) && ($value1['r2'] < $value2['r2'])){
                $seq = $value1['seq'].':'.$value2['seq'];
                //keep tail alive, but don't change key
                $tails2[$key2]['r1'] = $value2['r1'];
                $tails2[$key2]['r2'] = $value2['r2'];
                $tails2[$key2]['seq'] = $key2;
                if ($value2['r2'] >= $end){
                    $combos[] = $seq;
                } else {
                    $heads2[$h2]['r1'] = $value1['r2'];
                    $heads2[$h2]['r2'] = $value2['r2'];
                    $heads2[$h2]['seq'] = $seq;
                    $h2++;
                }
            }
        }
    }
    $heads = $heads2;
    $tails = $tails2;
}
这将显示以下内容:

2013/01/10 - 2013/01/26
2013/01/09 - 2013/01/15; 2013/01/14 - 2013/01/26
2013/01/10 - 2013/01/20; 2013/01/18 - 2013/01/27
2013/01/10 - 2013/01/20; 2013/01/19 - 2013/01/25
2013/01/10 - 2013/01/20; 2013/01/14 - 2013/01/26
2013/01/9 - 2013/01/15; 2013/01/14 - 2013/01/26
2013/01/09 - 2013/01/15; 2013/01/14 - 2013/01/19; 2013/01/18 - 2013/01/27
2013/01/09 - 2013/01/15; 2013/01/14 - 2013/01/19; 2013/01/19 - 2013/01/25
2013/01/09 - 2013/01/15; 2013/01/13 - 2013/01/19; 2013/01/18 - 2013/01/27
2013/01/09 - 2013/01/15; 2013/01/13 - 2013/01/19; 2013/01/19 - 2013/01/25
2013/01/9 - 2013/01/15; 2013/01/14 - 2013/01/19; 2013/01/18 - 2013/01/27
2013/01/9 - 2013/01/15; 2013/01/14 - 2013/01/19; 2013/01/19 - 2013/01/25
2013/01/9 - 2013/01/15; 2013/01/13 - 2013/01/19; 2013/01/18 - 2013/01/27
2013/01/9 - 2013/01/15; 2013/01/13 - 2013/01/19; 2013/01/19 - 2013/01/25

如果您可以找到
2013-01-09至2013-01-15
,我不确定为什么列表中缺少
2013-01-09至2013-01-15
,但您可以根据需要修改下面的此类

$range = [
        new DateManager("2013/01/08", "2013/01/10"),
        new DateManager("2013/01/09", "2013/01/15"),
        new DateManager("2013/01/10", "2013/01/20"),
        new DateManager("2013/01/18", "2013/01/27"),
        new DateManager("2013/01/14", "2013/01/19"),
        new DateManager("2013/01/19", "2013/01/25"),
        new DateManager("2013/01/14", "2013/01/26"),
        new DateManager("2013/01/10", "2013/01/26")
];

$find = new DateManager("2013/01/10", "2013/01/25");

foreach($range as $date) {
    $find->overlap($date) && print($date->getRange() . PHP_EOL);
}
输出

2013/01/09 to 2013/01/15 
2013/01/10 to 2013/01/20 
2013/01/14 to 2013/01/19 
2013/01/19 to 2013/01/25 
阶级

class DateManager {
    private $start, $end;

    function __construct($start, $end, $format = "Y/m/d") {
        $this->start = $start instanceof DateTime ? $start : DateTime::createFromFormat($format, $start);
        $this->end = $end instanceof DateTime ? $end : DateTime::createFromFormat($format, $end);
    }

    function getStart() {
        return $this->start;
    }

    function getEnd() {
        return $this->end;
    }

    function getRange($format = "Y/m/d") {
        return sprintf("%s to %s ", $this->start->format($format), $this->end->format($format));
    }

    function between(DateManager $date) {
        return $date->getStart() >= $this->getStart() && $this->getEnd() <= $date->end;
    }

    function overlap(DateManager $date) {
        return (($date->getStart() >= $this->getStart() || $date->getEnd() > $this->getStart()) && $this->getEnd() >= $date->getEnd());
    }
}
类数据管理器{
私人$开始$结束;
函数构造($start,$end,$format=“Y/m/d”){
$this->start=$start instanceof DateTime?$start:DateTime::createFromFormat($format,$start);
$this->end=$end instanceof DateTime?$end:DateTime::createFromFormat($format,$end);
}
函数getStart(){
返回$this->start;
}
函数getEnd(){
返回$this->end;
}
函数getRange($format=“Y/m/d”){
返回sprintf(“%s到%s”,$this->start->format($format),$this->end->format($format));
}
函数介于(DateManager$date){
返回$date->getStart()>=$this->getStart()&&&$this->getEnd()end;
}
函数重叠(DateManager$date){
return(($date->getStart()>=$this->getStart()|124;$date->getEnd()>$this->getStart())和&$this->getEnd()>=$date->getEnd());
}
}

将两个(开始、结束)日期转换为系统时间(从1/1/70开始,步长为1s),然后-运行步长为24*60*60的循环。如果需要,将每个值解码为可打印的形式。

到目前为止你做了什么?对我来说,这似乎是区间树的一个合适的用例。为什么列表中缺少
2013/01/10到2013/01/20
?@Baba-我认为这些只是示例,不包括所有示例。请注意,列表中有14到26个字符,超过了25个字符。因此,唯一可能不合格的是8到10,但这取决于重叠的定义。如果会议在10号结束,而乔在10号会议的最后一分钟出现,这是重叠吗?@Baba,因为我没有列出所有可能与输入日期范围重叠的日期范围。我只给出了两个与输入日期范围重叠的日期范围的示例。我想合并覆盖所有输入日期范围的所有日期范围。我想找到所有可能的日期范围组合,涵盖输入日期范围的所有日期。找到所有可能的组合是这个postfor(time_t i1=start;i1class DateManager { private $start, $end; function __construct($start, $end, $format = "Y/m/d") { $this->start = $start instanceof DateTime ? $start : DateTime::createFromFormat($format, $start); $this->end = $end instanceof DateTime ? $end : DateTime::createFromFormat($format, $end); } function getStart() { return $this->start; } function getEnd() { return $this->end; } function getRange($format = "Y/m/d") { return sprintf("%s to %s ", $this->start->format($format), $this->end->format($format)); } function between(DateManager $date) { return $date->getStart() >= $this->getStart() && $this->getEnd() <= $date->end; } function overlap(DateManager $date) { return (($date->getStart() >= $this->getStart() || $date->getEnd() > $this->getStart()) && $this->getEnd() >= $date->getEnd()); } }