本文已参与「新人创作礼」活动,一起开启掘金创作之路。
题目
给一个二维数组,每个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;
}
上面就是最大线段重合问题