面试题6:重叠区间个数

题目:给定多个可能重叠的区间,找出重叠区间的个数。

举例

    输入:[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))
}
 
 

猜你喜欢

转载自blog.csdn.net/qq_35191331/article/details/80228346
今日推荐