题目描述
现有若干个会议,所有会议共享一个会议室,用数组表示各个会议的开始时间和结束时间,格式为:
[[会议1开始时间, 会议1结束时间], [会议2开始时间, 会议2结束时间]]
请计算会议室占用时间段。
输入描述
第一行输入一个整数 n,表示会议数量
之后输入n行,每行两个整数,以空格分隔,分别表示会议开始时间,会议结束时间
输出描述
输出多行,每个两个整数,以空格分隔,分别表示会议室占用时间段开始和结束
备注
- 会议室个数范围:[1, 100]
- 会议室时间段:[1, 24]
用例
输入 | 4 1 4 2 5 7 9 14 18 |
输出 | 1 5 7 9 14 18 |
说明 |
输入:[[1,4],[2,5],[7,9],[14,18]] 输出:[[1,5],[7,9],[14,18]] 说明:时间段[1,4]和[2,5]重叠,合并为[1,5] |
输入 | 2 1 4 4 5 |
输出 | 1 5 |
说明 |
输入:[[1,4],[4,5]] 输出:[[1,5]] 说明:时间段[1,4]和[4,5]连续 |
题目解析
本题实际考试时为核心代码模式,非ACM模式,即无需处理输入输出。
本博客代码实现仍然以ACM模式处理,但是会将 "输入输出处理" 与 "核心代码" 分开,大家只看核心代码即可。
本题是区间合并问题。
我们可以将所有区间开始起始位置升序,然后取出第一个区间作为基准值pre,从第二个区间cur开始遍历:
- 如果 cur.start <= pre.end,则说明两个区间有重叠,此时我们应该将两个区间合并,合并策略是将pre.end = max(pre.end, cur.end),比如:
pre = [1, 4],cur = [2, 5],那么按此策略合并后,pre = [1, 5]
pre = [1, 100],cur = [7, 9],那么按此策略合并后,pre = [1, 100]
- 如果 cur.start > pre.end,则说明两个区间无交集,此时pre无法和后面任何区间合并(因为已经按照开始时间升序了,后面区间的开始时间肯定也大于pre.end),此时pre时间段就是一个独立的会议室占用时间,我们将它缓存记录下来,并将更新pre = cur,即将cur作为新的基准值和后面的区间比较
按此逻辑,即可完成所有区间的合并。
JS算法源码
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
// 输入输出处理
void (async function () {
const n = parseInt(await readline());
const roomTimes = [];
for (let i = 0; i < n; i++) {
roomTimes.push((await readline()).split(" ").map(Number));
}
merge(roomTimes).forEach(([start, end]) => console.log(`${start} ${end}`));
})();
// 本题实际考试时会核心代码模式,无需处理输入输出,只需要写出merge方法实现即可
function merge(roomTimes) {
// 将各个会议按照开始时间升序
roomTimes.sort((a, b) => a[0] - b[0]);
// 记录合并后的会议室占用时间段
const ans = [];
// 上一个会议占用时间段
let pre = roomTimes[0];
for (let i = 1; i < roomTimes.length; i++) {
// 当前会议占用时间段
const cur = roomTimes[i];
if (cur[0] <= pre[1]) {
// 当前会议开始时间 <= 上一个会议结束时间,则两个会议时间重叠,可以合并
// 注意合并时,结束时间取两个时间段中较大的结束时间
pre[1] = Math.max(pre[1], cur[1]);
} else {
// 否则不可以合并
ans.push(pre);
pre = cur;
}
}
ans.push(pre);
return ans;
}
Java算法源码
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
public class Main {
// 输入输出处理
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[][] roomTimes = new int[n][2];
for (int i = 0; i < n; i++) {
roomTimes[i][0] = sc.nextInt();
roomTimes[i][1] = sc.nextInt();
}
int[][] res = new Main().merge(roomTimes);
for (int[] time : res) {
System.out.println(time[0] + " " + time[1]);
}
}
// 本题实际考试时会核心代码模式,无需处理输入输出,只需要写出merge方法实现即可
public int[][] merge(int[][] roomTimes) {
// 将各个会议按照开始时间升序
Arrays.sort(roomTimes, (a, b) -> a[0] - b[0]);
// 记录合并后的会议室占用时间段
ArrayList<int[]> list = new ArrayList<>();
// 上一个会议占用时间段
int[] pre = roomTimes[0];
for (int i = 1; i < roomTimes.length; i++) {
// 当前会议占用时间段
int[] cur = roomTimes[i];
if (cur[0] <= pre[1]) {
// 当前会议开始时间 <= 上一个会议结束时间,则两个会议时间重叠,可以合并
// 注意合并时,结束时间取两个时间段中较大的结束时间
pre[1] = Math.max(pre[1], cur[1]);
} else {
// 否则不可以合并
list.add(pre);
pre = cur;
}
}
list.add(pre);
return list.toArray(new int[0][]);
}
}
Python算法源码
# 本题实际考试时会核心代码模式,无需处理输入输出,只需要写出merge方法实现即可
def merge(roomTimes):
# 将各个会议按照开始时间升序
roomTimes.sort(key=lambda x: x[0])
# 记录合并后的会议室占用时间段
ans = []
# 上一个会议占用时间段
pre = roomTimes[0]
for i in range(1, len(roomTimes)):
# 当前会议占用时间段
cur = roomTimes[i]
if cur[0] <= pre[1]:
# 当前会议开始时间 <= 上一个会议结束时间,则两个会议时间重叠,可以合并
# 注意合并时,结束时间取两个时间段中较大的结束时间
pre[1] = max(pre[1], cur[1])
else:
# 否则不可以合并
ans.append(pre)
pre = cur
ans.append(pre)
return ans
# 输入输出处理
n = int(input())
roomTimes = []
for _ in range(n):
roomTimes.append(list(map(int, input().split())))
for start, end in merge(roomTimes):
print(f"{start} {end}")
C算法源码
#include <stdio.h>
#include <stdlib.h>
int rows = 0;
int cmp(const void *a, const void *b) {
return (*(int **) a)[0] - (*(int **) b)[0];
}
// 本题实际考试时会核心代码模式,无需处理输入输出,只需要写出merge方法相关实现即可
int **merge(int **roomTimes, int roomTimes_size) {
// 将各个会议按照开始时间升序
qsort(roomTimes, roomTimes_size, sizeof(int *), cmp);
// 记录合并后的会议室占用时间段
int** res = (int**) malloc(sizeof(int*) * roomTimes_size);
// 上一个会议占用时间段
int* pre = roomTimes[0];
// 当前会议占用时间段
for(int i=1; i<roomTimes_size; i++) {
int* cur = roomTimes[i];
if(cur[0] <= pre[1]) {
// 当前会议开始时间 <= 上一个会议结束时间,则两个会议时间重叠,可以合并
// 注意合并时,结束时间取两个时间段中较大的结束时间
if(cur[1] > pre[1]) {
pre[1] = cur[1];
}
} else {
res[rows++] = pre;
pre = cur;
}
}
res[rows++] = pre;
return res;
}
// 输入输出处理
int main() {
int n;
scanf("%d", &n);
int **roomTimes = (int **) malloc(sizeof(int *) * n);
for (int i = 0; i < n; i++) {
roomTimes[i] = (int *) malloc(sizeof(int) * 2);
scanf("%d %d", &roomTimes[i][0], &roomTimes[i][1]);
}
int **res = merge(roomTimes, n);
for (int i = 0; i < rows; i++) {
printf("%d %dn", res[i][0], res[i][1]);
}
return 0;
}
免责声明:
1、IT资源小站为非营利性网站,全站所有资料仅供网友个人学习使用,禁止商用
2、本站所有文档、视频、书籍等资料均由网友分享,本站只负责收集不承担任何技术及版权问题
3、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除下载链接并致以最深的歉意
4、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
5、一经注册为本站会员,一律视为同意网站规定,本站管理员及版主有权禁止违规用户
6、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和IT资源小站的同意
7、IT资源小站管理员和版主有权不事先通知发贴者而删除本文
评论0