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

环形/周期性区间的最大相交数求解方案问询

解决环形/周期性区间的最大相交数问题

嘿,这个问题很有意思!既然你已经熟悉线性区间的解法,那我们可以把环形问题转化为线性问题来处理,核心思路是打破环形的“循环”特性,把它变成我们能处理的线性场景,下面分两种高效的方法来讲解:

方法一:双倍长度线性展开法(直观易实现)

这种方法的核心是把环形区间“展开”成两倍周期长度的线性空间,这样环形上的任意连续周期段,都能对应到这个线性空间里的一个长度为周期的窗口。具体步骤如下:

步骤1:确定周期长度

首先明确环形的周期长度,记为L(比如如果是0~20的环形,L=20)。

步骤2:生成事件点集合

对于每个环形区间[s, e]:

  • 如果s <= e(不跨周期端点):生成两个事件点:(s, +1)(区间开始,覆盖数+1)、(e, -1)(区间结束,覆盖数-1);同时复制这两个事件点,把时间加上L,得到(s+L, +1)、(e+L, -1)。
  • 如果s > e(跨周期端点,比如[18,3]在L=20时):同样生成原事件点(s, +1)、(e, -1),以及平移后的(s+L, +1)、(e+L, -1)。

注意:如果你的线性解法中是用e+1作为减1的触发点(避免区间端点重复计算),记得保持一致,这里用e是假设区间是闭区间[s,e]。

步骤3:排序事件点

把所有生成的事件点按时间从小到大排序;如果时间相同,优先处理+1的事件(和线性解法一致,确保区间端点处的覆盖数计算正确)。

步骤4:滑动窗口统计最大覆盖数

用双指针维护一个长度为L的滑动窗口:

  • 初始化左指针left=0,当前覆盖数current=0,最大相交数max_count=0。
  • 遍历每个右指针指向的事件点:
    1. 将当前事件的delta(+1或-1)加到current上。
    2. 移动左指针,移除所有时间 <= 当前事件时间 - L的事件:每次将current减去左指针事件的delta,然后左指针右移。
    3. 更新max_count为当前current和max_count中的较大值。

这个max_count就是环形区间的最大相交数。

方法二:分场景计算法(更高效,适合大数据量)

如果你的区间数量很大,双倍展开可能会占用较多内存,这时候可以分两种场景计算,取最大值:

场景1:最大相交数出现在非跨端点的线性段

直接用你熟悉的线性解法处理所有区间:

  • 把跨周期的区间拆成两个线性区间(比如[s,e](s>e)拆成[s,L]和[0,e])。
  • 用标记起止点、排序、遍历统计的方法,计算线性场景下的最大相交数,记为max_linear。

场景2:最大相交数出现在跨周期端点的位置

这种情况的相交数等于总区间数减去“完全落在环形某段空白区”的区间数量的最小值:

  1. 统计总区间数total = 所有区间的数量。
  2. 收集所有跨周期区间的e(右端点,0L)和`s`(左端点,0L),我们要找的空白区是环形上未被任何跨周期区间覆盖的部分,也就是所有[e_i, s_i]的交集(所有跨周期区间都不覆盖的区域)。
  3. 统计完全落在这个空白区里的非跨周期区间的数量,找到这个数量的最小值min_gap。
  4. 跨端点场景的最大相交数为total - min_gap(因为所有跨周期区间都覆盖端点位置,加上非跨周期区间中不落在空白区的部分)。

最终结果

环形区间的最大相交数 = max(max_linear, total - min_gap)

例子验证

比如你给出的线性区间[1,6]、[2,5]、[5,10]、[12,17],假设周期L=20(无跨周期区间):

  • 方法一:双倍展开后滑动窗口统计的最大覆盖数是3,和线性结果一致。
  • 方法二:max_linear=3,由于没有跨周期区间,跨端点场景的计算不适用,直接取max_linear即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:13:58