给定 n 个区间 [li,ri],要求合并所有有交集的区间。
注意如果在端点处相交,也算有交集。
输出合并完成后的区间个数。
例如:[1,3]和[2,6]可以合并为一个区间[1,6]。
输入格式
第一行包含整数n。
接下来n行,每行包含两个整数 l 和 r。
输出格式
共一行,包含一个整数,表示合并区间完成后的区间个数。
数据范围
1≤n≤100000,
−109≤li≤ri≤109
输入样例:
5
1 2
2 4
5 6
7 8
7 9
输出样例:
3
Go 代码
package main
import (
"bufio"
"fmt"
"math"
"os"
"sort"
"strconv"
"strings"
)
type pair struct { // 存储区间
first int // 区间左端点
second int // 区间右端点
}
func main() {
// file, _ := os.Open("./1.txt")
// defer file.Close()
scanner = bufio.NewScanner(os.Stdin)
bs := make([]byte, 20000*1024)
scanner.Buffer(bs, len(bs))
var n = readline()[0]
segs := make([]pair, 0)
for i := 0; i < n; i++ {
x := readline()
segs = append(segs, pair{x[0], x[1]}) // 读入每个区间的左右端点
}
// 调用区间合并模板
res := merge(segs)
fmt.Println(len(res))
}
func merge(segs []pair) []pair {
var res []pair // 定义区间合并后的结果
sort.Slice(segs, func(i, j int) bool {
if segs[i].first == segs[j].first {
return segs[i].second < segs[j].second
} // 优先以左端点大小排序
return segs[i].first < segs[j].first
})
// 从左往右扫描,维护当前区间
start, end := math.MinInt32, math.MinInt32 // 边界设为负无穷到正无穷
for _, seg := range segs {
if end < seg.first { // 没有交集
if start != math.MinInt32 {
res = append(res, pair{start, end})
}
start, end = seg.first, seg.second
} else { // 有交集
if seg.second > end {
end = seg.second
}
}
}
if start != math.MinInt32 { // 避免 segs 为空
res = append(res, pair{start, end})
}
return res // 更新维护的当前区间
}
var scanner *bufio.Scanner
func readline() []int {
scanner.Scan()
l := strings.Split(scanner.Text(), " ")
res := make([]int, len(l))
for i, s := range l {
x, _ := strconv.Atoi(s)
res[i] = x
}
return res
}