【算法训练】LeetCode#56 合并区间
一、描述
56. 合并区间
以数组 intervals
表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi]
。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
示例 1:
输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:
输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。
二、思路
类似于括号匹配?简单尝试一下再说。
其实写的有些问题,但是也能够ac。
- 先按照val做排序,然后遇到left就++,遇到right就--
- 如此往复,知道没有变化时就是最简ans。
三、解题
public class LeetCode56 {
public static class Info{
int val; // 边界
char tip; // l or r
public Info(int v,char t){
val = v;
tip = t;
}
}
public static int[][] merge(int[][] intervals) {
PriorityQueue<Info> infoList = new PriorityQueue<>(new Comparator<Info>() {
@Override
public int compare(Info o1, Info o2) {
if (o1.val != o2.val){
return o1.val - o2.val;
} else {
// 如果val相等,则让l在前
return o1.tip == 'l' ? 0 : 1;
}
}
}); // 升序
for (int[] val : intervals){
infoList.add(new Info(val[0],'l'));
infoList.add(new Info(val[1],'r'));
}
int temp = 0;
int curLeft = Integer.MAX_VALUE;
int curRight = Integer.MIN_VALUE;
int lastSize = -1;
LinkedList<int[]> ans = new LinkedList<>();
while (true){
while (!infoList.isEmpty()){
Info info = infoList.poll();
if (info.tip == 'l'){
temp++;
curLeft = Math.min(curLeft, info.val);
}
if (info.tip == 'r'){
temp--;
curRight = Math.max(curRight, info.val);
}
if (temp == 0){
// 凑成完整一组
ans.add(new int[]{curLeft,curRight});
curLeft = Integer.MAX_VALUE;
curRight = Integer.MIN_VALUE;
}
}
if (lastSize == ans.size()){
break;
}
lastSize = ans.size();
while (!ans.isEmpty()){
int[] info = ans.poll();
infoList.add(new Info(info[0],'l')); // 继续排序
infoList.add(new Info(info[1],'r')); // 继续排序
}
}
int n = ans.size();
int[][] result = new int[n][2];
for (int i = 0 ; i < n ; i++){
result[i][0] = ans.get(i)[0];
result[i][1] = ans.get(i)[1];
}
return result;
}
public static void main(String[] args) {
int[][] input = new int[][]{{2,3},{0,1},{1,2},{3,4},{4,5},{1,1},{0,1},{4,6},{5,7},{1,1},{3,5}};
merge(input);
}
}