题目
给定一组闭区间,其中部分区间存在交集。
任意两个给定区间的交集,称为公共区间 (如 [1,2],[2,3] 的公共区间为 [2,2],[3,5],[3,6] 的公共区间为 [3,5])。
公共区间之间若存在交集,则需要合并 (如 [1,3],[3,5] 区间存在交集 [3,3],需合并为 [1,5])。
按升序排列输出合并后的区间列表。
输入描述
一组区间列表,
区间数为 N: 0<=N<=1000;
区间元素为 X: -10000<=X<=10000。
输出描述
升序排列的合并区间列表
备注
1、区间元素均为数字,不考虑字母、符号等异常输入。
2、单个区间认定为无公共区间。
用例
输入 | 输出 | 说明 |
---|---|---|
4 0 3 1 3 3 5 3 6 | 1 5 | [0,3] 和 [1,3] 的公共区间为 [1,3], [0,3] 和 [3,5] 的公共区间为 [3,3], [0,3] 和 [3,6] 的公共区间为 [3,3], [1,3] 和 [3,5] 的公共区间为 [3,3], [1,3] 和 [3,6] 的公共区间为 [3,3], [3,5] 和 [3,6] 的公共区间为 [3,5], 公共区间列表为 [[1,3],[3,3],[3,5]]; [[1,3],[3,3],[3,5]] 存在交集,须合并为 [1,5]。 |
4 0 3 1 4 4 7 5 8 | 1 3 4 4 5 7 |
思考
- 提取公共区间:首先找出所有两两区间的交集,作为公共区间。
- 合并重叠公共区间:将提取的公共区间按起点排序,然后合并重叠或相邻的区间。
算法过程
- 输入处理:读取区间列表,存储为二维数组。
- 计算公共区间:遍历每对区间,计算它们的交集。若交集存在(起点≤终点),则加入公共区间列表。
- 排序公共区间:按公共区间的起点升序排序。
- 合并区间:遍历排序后的公共区间,合并重叠或相邻的区间(当前区间起点≤前一区间终点时合并)。
参考代码
function solution() {
const N = parseInt(readline());
if (N <= 1) { // 单个区间或无区间,直接输出空
console.log('');
return;
}
const list = [];
for (let i = 0; i < N; i++) {
const [start, end] = readline().split(' ').map(Number);
list.push({ start, end });
}
// 提取所有两两区间的公共区间
const commonIntervals = [];
for (let i = 0; i < N; i++) {
const a = list[i];
for (let j = i + 1; j < N; j++) {
const b = list[j];
const start = Math.max(a.start, b.start);
const end = Math.min(a.end, b.end);
if (start <= end) {
commonIntervals.push({ start: start, end: end });
}
}
}
if (commonIntervals.length === 0) { // 无公共区间
console.log('');
return;
}
// 按起点排序公共区间
commonIntervals.sort((x, y) => x.start - y.start);
// 合并重叠区间
const merged = [commonIntervals[0]];
for (let i = 1; i < commonIntervals.length; i++) {
const curr = commonIntervals[i];
const last = merged[merged.length - 1];
if (curr.start <= last.end) { // 合并条件:当前起点 ≤ 前一终点
merged[merged.length - 1] = {
start: last.start,
end: Math.max(last.end, curr.end)
};
} else {
merged.push(curr);
}
}
// 输出结果
const output = merged.map(interval => `${interval.start} ${interval.end}`).join('\n');
console.log(output);
}
const cases = [
`4
0 3
1 3
3 5
3 6`,
`4
0 3
1 4
4 7
5 8`
];
let caseIndex = 0;
let lineIndex = 0;
const readline = (function () {
let lines = [];
return function () {
if (lineIndex === 0) {
lines = cases[caseIndex]
.trim()
.split("\n")
.map((line) => line.trim());
}
return lines[lineIndex++];
};
})();
cases.forEach((_, i) => {
caseIndex = i;
lineIndex = 0;
solution();
});