最大线段重合问题

263 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目

给一个二维数组,每个arr[i]里面都有两个元素,表示一个线段的开始和结束,而且是开区间的。问:有多少个线段是重合的。

思路

我们这个题目是用堆解决的。我们准备一个小根堆,然后让数组按照开始位置从小到大排序。排好之后,先拿到第一个线段的开始,让小根堆弹出比开始小且等于的元素,然后把结尾的值放到小根堆里面,这个时候小根堆有几个元素就是这个值的答案,然后以此往复,算出了所有线段的答案,然后找到最大值。

这个是为什么呢?

线段第一个排序之后,所有的线段都是从前往后的,那我们拿到某一个线段的开始,然后利用这个开始,弹出小根堆里面的元素这个是为什么?

我们想想小根堆里面放的都是什么?

是结尾!

那么比开始小的值弹出,是不是排除了不能重合的线段。

然后再把自己的结尾放进去。

举例

数组[[1,7],[4,6],[7,9]]

这个时候我们创建一个小根堆【】

然后我们先排序数组,

这个时候我们哪第一个线段【1,7】

我们先弹出小根堆里面比1小且等于的元素,弹出之后放进7

小根堆【7】这个时候有多少个元素就是这个线段的答案。

之后我们拿到第二个线段【4,6】

我们弹出比4小且等于的元素,弹出之后放进6

小根堆【7,6】这个时候有多少个元素就是这个线段的答案。

这个时候我们拿第三个线段【7,9】

我们先弹出小根堆里面比7小且等于的元素,弹出之后放进9

小根堆【9】这个时候有多少个元素就是这个线段的答案。

最后最大线段重合问题的答案就是2;

代码

public static int maxCover(int[][] lines){
    Arrays.sort(lines , (a,b)->a[0]-b[0]);
    PriorityQueue<Integer> queue = new PriorityQueue<>();
    int max = 0;
    for(int[] cur:lines){
        while(!queue.isEmpty() && cur[0] >= queue.peek()){
            queue.poll();
        }
        queue.add(cur[1]);
        max = Math.max(max , queue.size());
    }
    return max;
}

上面就是最大线段重合问题