← 返回题目列表

删除一个区间后剩余区间如何计算?相交部分为什么要切成左右两段?

中等 第 23 / 24 题 更新于 2026/08/01
区间问题区间删除分类讨论数组

简化版

删除区间 [a,b] 时,遍历每个原区间 [l,r]。如果它和删除区间不相交,原样保留;如果相交,则保留左侧残段 [l,a] 中合法部分和右侧残段 [b,r] 中合法部分,注意常见题目使用半开区间 [l,r)

详细版

区间删除的核心是分类讨论。对于半开区间 [l,r) 和删除区间 [a,b):若 r <= al >= b,说明不相交;否则相交。相交时,如果 l < a,保留 [l,a);如果 r > b,保留 [b,r)

每个区间最多产生两个残段,时间复杂度 O(n),空间复杂度 O(n)。面试重点是端点语义:半开区间下端点相等不算重叠。

完整版教学

一、先确认端点语义

很多删除区间题使用半开区间 [start,end),表示包含 start,不包含 end。这样 [1,3)[3,5) 不相交。

语义[1,3][3,5][1,3)[3,5)
闭区间相交不适用
半开区间不适用不相交

易错点:区间删除题先看是闭区间还是半开区间,判断不相交条件会不同。

下面按常见半开区间讲。

二、不相交时为什么原样保留

原区间 [l,r) 和删除区间 [a,b) 不相交有两种情况:

r <= a  // 原区间在删除区间左边
l >= b  // 原区间在删除区间右边

这时删除操作不会影响原区间,直接加入答案。

[1,2) 删除 [3,4) => [1,2)

三、相交时为什么可能产生两段

如果原区间覆盖删除区间的左右两侧,删除中间后会裂成两段。

原区间:[1,10)
删除:    [3,7)
剩余:[1,3) 和 [7,10)

所以不能只修改一个端点就结束。要分别检查左残段和右残段是否存在。

四、左残段和右残段的条件

左残段存在条件:

l < a
保留 [l, a)

右残段存在条件:

r > b
保留 [b, r)
原区间位置剩余
完全被删除覆盖
只左侧剩余[l,a)
只右侧剩余[b,r)
两侧都剩余两段

这些条件直接来自半开区间的合法长度必须大于 0。

五、代码模板

List<List<Integer>> removeInterval(int[][] intervals, int[] toBeRemoved) {
    int a = toBeRemoved[0], b = toBeRemoved[1];
    List<List<Integer>> ans = new ArrayList<>();
    for (int[] in : intervals) {
        int l = in[0], r = in[1];
        if (r <= a || l >= b) {
            ans.add(Arrays.asList(l, r));
        } else {
            if (l < a) ans.add(Arrays.asList(l, a));
            if (r > b) ans.add(Arrays.asList(b, r));
        }
    }
    return ans;
}

如果平台要求返回 int[][],最后再把列表转换成数组即可。

六、用例子推演

intervals=[[0,2],[3,4],[5,7]],删除 [1,6)

[0,2) 与 [1,6) 相交,剩 [0,1)
[3,4) 被完全删除,剩无
[5,7) 相交,剩 [6,7)

结果是 [[0,1],[6,7]]。注意 [3,4) 没有残段,因为它完全落在删除区间内。

七、常见误区与追问

  • 误区:把半开区间端点相等当重叠。 [1,3)[3,5) 不相交。
  • 误区:相交时只保留一边。 删除中间时可能裂成左右两段。
  • 误区:产生空区间。 只有 l<ar>b 时才保留残段。
  • 追问:如果是闭区间怎么办? 残段端点要改成 [l,a-1][b+1,r] 这类形式,取决于整数还是连续域。
  • 追问:原区间需要排序吗? 若题目保证已排序不重叠,输出自然有序;否则删除逻辑仍可逐段做。
  • 追问:复杂度是多少? 每个区间最多处理一次,时间 O(n)

八、加强记忆

删除区间的核心是“没碰到就原样,碰到了就切掉中间”。半开区间下,不相交条件是 r<=al>=b;相交时左边看 l<a,右边看 r>b。最容易错的是端点语义和中间删除导致的一分为二。