题目:给定多个可能重叠的区间,找出重叠区间的个数。
举例
输入:[1,5],[10,15],[5,10],[20,30]
输出:3
解法一:常规解法,就是我们一上来,最先想到的方法就是使用暴力破解,直接扫描,先第一个区间开始,看这个区间是不是在后面其他区间里面,两两区间判断是否重叠的方式,用一个数组存放区间是否存在重叠,如果两个区间重叠,比如第一个区间和第五个区间重叠,则把数组下标0,4这个两个设置为true,或其他标识。当第一个区间扫描完后面的区间,换到第二个区间。。。直到最后一个区间。最后面扫描这个数组,计算标识过的个数,即重叠区间个数。这种方法的时间复杂度达到O(n^2)
解法二:
(1)将区间值放入到结构体数组中{值,开始或者结束,第几个区间}
(2)对这个结构体数组进行排序(规则:值从小到大,相同的值按起始点为先,值相同且都是起点值,则按照之前数组顺序)
(3)然后开始找哪些区间属于叠加区间的,用一个count=0标记,遇到开始值,则count++,否则count--,如果count>1,则说明当且区间与某个区间重叠,如果前一个值是一个区间的开始值,则会重叠,则标记这两个区间,否则标记当前区间,重复,直到区间遍历完成。
(4)遍历数组,计算出现的区间数
(5)返回最大叠加区间数
例如:
给定一个区间:[1,5],[2,3],[5,10],[6,12],[15,20],根据上面的分析思路,可以得出以下步骤
[1,5],[2,3],[5,10],[6,12],[15,20]
0 1 0 1 0 1 0 1 0 1
1 1 2 2 3 3 4 4 5 5
(1)构造结构体数组:{1,0,1},{5,1,1},{2,0,2},{3,1,2},{5,0,3},{10,1,3},{6,0,4},{12,1,4},{15,0,5},{20,1,5}
(2)排序之后:{1,0,1}{2,0,2}{3,1,2}{5,0,3}{5,1,1}{6,0,4}{10,1,3}{12,1,4}{15,0,5}{20,1,5}
(3)这边一共有5个区间,所以定义一个长度为5的bool数组flag[5],初始为false,如果为叠加区间,则设为true,
{1,0,1},这边为0,所以count++,count值1
{2,0,2},这边为0,所以count++,count值2,又因为前面一个是0,所以该区间与上一个值对于的区间存在重叠,flag[0]=flag[1]=true
{3,1,2},这边为1,所以count--,count值1
{5,0,3},这边为0,所以count--,count值2,flag[2]=true
{5,1,1},这边为1,所以count--,count值1
{6,0,4},这边为0,所以count++,count值2,flag[3]=true
{10,1,3},这边为1,所以count--,count值1
{12,1,4},这边为1,所以count--,count值0
{15,0,5},这边为0,所以count++,count值1
{20,1,5},这边为1,所以count--,count值0
遍历数组:叠加区间有四个
代码实现如下:
package main
import (
"fmt"
"sort"
)
type Interval struct {
start int
end int
}
type PointSlice []Point
func (p PointSlice) Len() int { // 重写 Len() 方法
return len(p)
}
func (p PointSlice) Swap(i, j int) { // 重写 Swap()方法
p[i], p[j] = p[j], p[i]
}
func (p PointSlice) Less(i, j int) bool { // 重写 Less
if (p[i].v < p[j].v) ||
(p[i].v == p[j].v && p[i].t == 0 && p[j].t == 1) {
return true
}
return false
}
type Point struct {
v int
t int
n int
}
func getOverlappingCount(a []Interval) int {
max, count, length := 0, 0, len(a)
if length == 0 || length == 1 {
return length
}
points := make([]Point, length*2)
for i := 0; i < length; i += 1 {
points[i*2] = Point{a[i].start, 0, i}
points[i*2+1] = Point{a[i].end, 1, i}
}
flag := make([]bool, length)
// 排序
sort.Sort(PointSlice(points))
length *= 2
for i := 0; i < length; i += 1 {
if points[i].t == 0 {
count++
} else {
count--
}
if count > 1 {
flag[points[i].n] = true
if points[i].t == 0 {
flag[points[i-1].n] = true
}
}
}
length /= 2
for i := 0; i < length; i += 1 {
if flag[i] {
max += 1
}
}
// 存在多个区间,但是这些区间之间都不存在重叠,那么这种情况的话,重叠区间算一个
if max == 0 {
max = 1
}
return max
}
func main() {
// 测试用例
a := []Interval{Interval{1, 5}, Interval{10, 15}, Interval{5, 10}, Interval{20, 30}}
fmt.Println(getOverlappingCount(a))
}