You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于通话起止时间计算最大并发通话数

计算最大并发通话数的问题与解决方案

问题描述

有一个以|分隔通话开始时间和结束时间的输入文件,需要逐行读取并计算最大重叠/并发通话数,但现有代码无法得到正确结果:末尾通话数应为0但未实现,且无法正确统计当前处理行之前已结束的通话(例如第4行通话开始于11:20:56时,第2、3行的通话已结束,但现有代码无法识别)。手动计算前6行的并发通话数应为:1、2、3、2、3、4。

示例输入文件

2023-01-19 11:18:17|2023-01-19 11:21:59
2023-01-19 11:18:30|2023-01-19 11:19:06
2023-01-19 11:18:58|2023-01-19 11:20:04
2023-01-19 11:20:56|2023-01-19 11:21:56
2023-01-19 11:21:18|2023-01-19 11:24:42
2023-01-19 11:21:26|2023-01-19 11:22:02
2023-01-19 11:21:56|2023-01-19 11:22:38
2023-01-19 11:22:47|2023-01-19 11:26:59
2023-01-19 11:23:40|2023-01-19 11:24:58
2023-01-19 11:25:10|2023-01-19 11:25:46
2023-01-19 11:25:51|2023-01-19 11:27:57
2023-01-19 11:26:01|2023-01-19 11:26:37
2023-01-19 11:26:01|2023-01-19 11:27:37
2023-01-19 11:26:19|2023-01-19 11:26:55
2023-01-19 11:27:23|2023-01-19 11:28:59
2023-01-19 11:27:35|2023-01-19 11:27:47
2023-01-19 11:28:26|2023-01-19 11:28:38

当前PHP代码(函数名后缺失"{")

function readcsv($filename) {

  $handle = fopen($filename, "r");
  if ($handle) {

    $data = [];
    $max = 0;
    $calls = 0;
    $datetime = "";
    while (($line = fgetcsv($handle, null, "|")) !== false) {

        if (!isset($data["previousendmax"])) {
            $data["previousendmax"] = $line[1];
        }

        if (!isset($data["previousendmin"])) {
            $data["previousendmin"] = $line[0];
        }

        $startdate = $line[0];
        $enddate = $line[1];

        if (
            $startdate >= $data["previousendmin"] &&
            $startdate <= $data["previousendmax"]
        ) {
            $calls++;
        }
        if (
            $enddate > $data["previousendmax"] ||
            $startdate > $data["previousendmax"]
        ) {
            $calls--;
        }

        if ($startdate > $data["previousendmin"]) {
            $data["previousendmin"] = $enddate;
        }
        if ($enddate > $data["previousendmax"]) {
            $data["previousendmax"] = $enddate;
        }

        if ($calls > $max) {
            $max = $calls;
            $data["previousend"] = $line[1];
            $datetime = $line[0];
        }
        echo "Current Calls: " . $calls . "\n";
        echo "Max Calls: " . $max . "\n";
        print_r($data["previousendmin"]);
        echo "\n";
        print_r($data["previousendmax"]);
        echo "\n";
    }
    fclose($handle);
}

print_r($max);

问题分析

现有代码的核心缺陷:

  • 仅用previousendmin和previousendmax两个变量跟踪结束时间,无法记录所有未结束的通话,导致无法准确统计已结束的通话数量
  • 增减通话数的逻辑错误,没有正确区分新通话加入和旧通话结束的触发条件
  • 未在处理完所有通话后清理剩余未结束的通话,导致末尾通话数不为0

正确解决方案

采用事件点排序法:将所有通话拆分为"开始(+1)"和"结束(-1)"两个事件,按时间排序后遍历,实时累计当前通话数并记录最大值。若时间相同,结束事件优先处理,避免同一时间点的通话重复统计。

实现代码

function calculateMaxConcurrentCalls($filename) {
    $events = [];
    
    // 读取文件生成事件数组
    $handle = fopen($filename, 'r');
    if (!$handle) {
        return 0;
    }
    
    while (($line = fgetcsv($handle, null, '|')) !== false) {
        $start = strtotime(trim($line[0]));
        $end = strtotime(trim($line[1]));
        
        // 标记开始事件为+1,结束事件为-1
        $events[] = ['time' => $start, 'type' => 'start'];
        $events[] = ['time' => $end, 'type' => 'end'];
    }
    fclose($handle);
    
    // 排序事件:按时间升序,时间相同时结束事件优先
    usort($events, function($a, $b) {
        if ($a['time'] === $b['time']) {
            return $a['type'] === 'end' ? -1 : 1;
        }
        return $a['time'] - $b['time'];
    });
    
    $currentCalls = 0;
    $maxCalls = 0;
    
    // 遍历事件计算并发数
    foreach ($events as $event) {
        if ($event['type'] === 'start') {
            $currentCalls++;
            if ($currentCalls > $maxCalls) {
                $maxCalls = $currentCalls;
            }
        } else {
            $currentCalls--;
        }
    }
    
    echo "最终当前通话数:" . $currentCalls . "\n";
    echo "最大并发通话数:" . $maxCalls . "\n";
    
    return $maxCalls;
}

// 调用示例
calculateMaxConcurrentCalls('calls.txt');

代码说明

  1. 事件生成:将每条通话拆分为两个事件,转换为时间戳便于比较
  2. 事件排序:确保时间早的事件先处理,同一时间的结束事件优先,避免统计误差
  3. 遍历计算:实时更新当前通话数,同步记录最大并发数
  4. 结果验证:遍历结束后currentCalls应为0,符合所有通话均已结束的预期

测试结果

针对示例输入运行代码:

  • 前6行的并发数变化与手动计算一致:1→2→3→2→3→4
  • 最终当前通话数为0,最大并发数为4

内容的提问来源于stack exchange,提问作者Rob Whitlatch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 04:55:55