logo
Home 特权副本 算法——关于区间重叠的几个问题

算法——关于区间重叠的几个问题

  • 2026-08-10 10:37:39

区间重叠的问题:给定包含起始时间s和终止时间t(s < t) 的n个区间段,依据区间重叠情况衍生出来的一系列问题,一般以会议室的安排为外壳作为题目,给定n个会议的开始和结束时间,求相关问题,输入格式为:

n

s1 t1

s2 t2

...

sn tn

以下整理了三种常见题目:

1、最少会议室(最多重叠区间数)

求满足所有会议安排的最少会议室数量。即最多的相互重叠的区间数量。

如上图分析可知,可将所有时间点排序,初始化ans=0,遇到起始点+1,遇到终止点-1,即可得到任意区间段的区间重叠数量。

特殊情况:当同一区间点同时为起始点和终止点时(图中+0点),需将终止点标记排在起始点之前,即先-1再+1,否则会出现错误。

时间复杂度:时间主要耗费在排序2n个元素上,复杂度为O(nlogn)。

基于C++的示例代码如下:

1 #include

2 #include

3 using namespace std;

4

5 bool cmp(const pair x, const pair y){

6 // 对于相同的区间点,使终点始终在起点之前

7 if(x.first == y.first) return x.second > y.second;

8 return x.first < y.first;

9 }

10

11 int main(){

12 int n, s, t;

13 vector > vals;

14 cin >> n;

15

16 for(int i = 0; i < n; i++){

17 cin >> s >> t;

18 vals.push_back(pair(s, 0));

19 vals.push_back(pair(t, 1));

20 }

21 sort(vals.begin(), vals.end(), cmp);

22

23 int K = 0, ans = 0;

24 for(int i = 0; i < vals.size(); i++){

25 // 遇到起点+1

26 if(vals[i].second == 0){

27 K++;

28 ans = ans > K ? ans : K;

29 }

30 // 遇到终点-1

31 else K--;

32 }

33 cout << ans << endl;

34 return 0;

35 }

2、最多数量会议安排(最多无重叠的区间数量)

在仅有一个会议室的情况下,求最多能满足的会议数量。即最多的无相互重叠的区间数量。

如上图所示,可用贪心法解决,按照会议结束时间排序,首先取第一个结束的会议,并记录结束时间end_t(图中红色点),依次遍历后续会议,若某会议的开始时间不小于end_t(图中蓝色点),则可安排该会议,同时更新end_t。

特殊情况:当结束时间相等时,开始时间的顺序其实无关紧要,如上图第三四行,两个会议均可,且安排后end_t相同,对后续安排不影响;若同时要求优先安排较长时间的会议、或者保证会议室总使用时间较长,可以在结束时间相等的情况下,使开始时间升序排列。

时间复杂度:时间主要耗费在排序n个元素上,复杂度为O(nlogn)。

基于C++的示例代码如下:

1 #include

2 #include

3 using namespace std;

4

5 bool cmp(const pair x, const pair y){

6 // 对于结束时间相同的,按起始时间升序排列

7 if(x.second == y.second) return x.first < y.first;

8 // 按结束时间升序排列

9 return x.second < y.second;

10 }

11

12 int main(){

13 int n, s, t;

14 vector > vals;

15 cin >> n;

16

17 for(int i = 0; i < n; i++){

18 cin >> s >> t;

19 vals.push_back(pair(s, t));

20 }

21 sort(vals.begin(), vals.end(), cmp);

22

23 int end_t = -1, ans = 0;

24 for(int i = 0; i < vals.size(); i++){

25 // 若当前会议开始时间不小于上一个安排会议的结束时间,则可安排

26 if(vals[i].first >= end_t){

27 ans++;

28 end_t = vals[i].second;

29 }

30 }

31 cout << ans << endl;

32 return 0;

33 }

3、最长时间会议安排(最多无重叠的区间长度)

在仅有一个会议室的情况下,求最长的能满足的会议时间。即最多无相互重叠的区间长度。

该问题用动态规划解决,首先将会议按结束时间排序,dp[i]表示以安排第i个会议作为最后一个会议时前i个会议能满足的最长时间,递推关系为dp[i] = (ti - si) + MAX{dp[j]},其中0<=j= tj。

特殊情况:对于结束时间相等的会议,按照开始时间顺序排序。

时间复杂度:排序n个元素复杂度为O(nlogn),动态规划复杂度为O(n2),整体复杂度为O(n2)。

基于C++的示例代码如下:

1 #include

2 #include

3 #include

4 using namespace std;

5

6 bool cmp(const pair x, const pair y){

7 // 对于结束时间相同的,按起始时间升序排列

8 if(x.second == y.second) return x.first < y.first;

9 // 按结束时间升序排列

10 return x.second < y.second;

11 }

12

13 int main(){

14 int n, s, t;

15 vector > vals;

16 cin >> n;

17

18 for(int i = 0; i < n; i++){

19 cin >> s >> t;

20 vals.push_back(pair(s, t));

21 }

22 sort(vals.begin(), vals.end(), cmp);

23

24 vector dp(n, 0);

25 int ans = 0;

26 for(int i = 0; i < vals.size(); i++){

27 int mmax = 0;

28 for(int j = 0; j < i; j++){

29 // mmax = max{dp[j]}, for all 0 <= j < i and si >= tj

30 if((vals[i].first >= vals[j].second) && (dp[j] > mmax)){

31 mmax = dp[j];

32 }

33 }

34 // dp[i] = (ti - si) + max{dp[j]}

35 dp[i] = vals[i].second - vals[i].first + mmax;

36 ans = ans > dp[i] ? ans : dp[i];

37 }

38 cout << ans << endl;

39 return 0;

40 }

Previous Post
46岁邓超综艺“封神”,从“跑男”到“五哈”再到“奋斗吧”,他凭什么越活越少年
Copyright © 2088 战力飙升活动特区 - 专属特权限时解锁 All Rights Reserved.
友情链接