合并区间
一、题目描述:
给出一个区间的集合,请合并所有重叠的区间。
(题目来源:力扣(LeetCode))
示例 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] 可被视为重叠区间。
二、解决方法:
- 优化后的希尔排序(可以选择其它的排序方法)+合并区间
package com.lxf.sort;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
public class Merge {
public static void main(String[] args) {
int[][] result=merge(new int[][] {
{
8,10},{
1,6},{
15,18},{
2,7}});
for (int i = 0; i < result.length; i++) {
System.out.print("["+result[i][0]+","+result[i][1]+"]");
}
}
public static int[][] merge(int[][] intervals) {
//处理掉一些特殊情况
if(intervals==null) return null;
int length=intervals.length;
if(length==1||length==0){
return intervals;}
//排序二维数组:优化过的希尔排序算法
for(int d=length/2;d>0;d/=2){
for(int i=d;i<length;i++) {
int j=i;
int m=intervals[j][0];
int n=intervals[j][1];
while(j-d>=0&&m<intervals[j-d][0]) {
intervals[j][0]=intervals[j-d][0];
intervals[j][1]=intervals[j-d][1];
j-=d;
}
if(j!=i) {
intervals[j][0]=m;
intervals[j][1]=n;
}
}
}
//用队列帮助我们进行和并区间
Queue<Integer> queue=new LinkedList<Integer>();
//标识合并之后数组的下标
int j=0;
for (int i = 0; i < length; i++) {
//如果对列为空直接将这个数组加入队列(用i下标代替)
if(queue.isEmpty()) {
queue.offer(i);
}else {
//如果队列中的值和数组当前的值发生重叠的时候
//合并这两个区间
if(intervals[queue.peek()][1]>=intervals[i][1]){
continue;
}else if(intervals[queue.peek()][1]>=intervals[i][0]){
intervals[queue.peek()][1]=intervals[i][1];
}else{
//先将这个数组加入队列
queue.offer(i);
//再将队列头的数组poll出去
int k=queue.poll();
intervals[j][0]=intervals[k][0];
intervals[j][1]=intervals[k][1];
j++;
}
}
}
//循环后如果队列还是有值就取出,插入到新数组的后面
if(!queue.isEmpty()){
int k=queue.poll();
intervals[j][0]=intervals[k][0];
intervals[j][1]=intervals[k][1];
j++;
}
//循环完后j就是我们要的数组的长度,将intervals分割后就是我们的答案了
return Arrays.copyOf(intervals, j);
}
}
再次优化和并区间:
package com.lxf.sort;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
public class Merge {
public static void main(String[] args) {
int[][] result=new int[][] {
{
8,10},{
1,6},{
15,18},{
2,7}};
// Arrays.sort(result,(a,b)->a[0]-b[0]);
Arrays.sort(result, Comparator.comparingInt(a->a[0]));
for (int i = 0; i < result.length; i++) {
System.out.print("["+result[i][0]+","+result[i][1]+"]");
}
}
public static int[][] merge(int[][] intervals) {
//处理掉一些特殊情况
if(intervals==null) return null;
int length=intervals.length;
if(length==1||length==0){
return intervals;}
//排序二维数组:优化过的希尔排序算法
for(int d=length/2;d>0;d/=2){
for(int i=d;i<length;i++) {
int j=i;
int m=intervals[j][0];
int n=intervals[j][1];
while(j-d>=0&&m<intervals[j-d][0]) {
intervals[j][0]=intervals[j-d][0];
intervals[j][1]=intervals[j-d][1];
j-=d;
}
if(j!=i) {
intervals[j][0]=m;
intervals[j][1]=n;
}
}
}
//用于存储结果集的集合
ArrayList<int[]> results = new ArrayList<>();
int i=0;
while(i<length){
int left = intervals[i][0];
int right = intervals[i][1];
// 如果有重叠,循环判断哪个起点满足条件
while (i < length - 1 && intervals[i + 1][0] <= right) {
i++;
right = Math.max(right, intervals[i][1]);
}
// 将现在的区间放进res里面
results.add(new int[]{
left, right});
// 接着判断下一个区间
i++;
}
return results.toArray(new int[0][]);
}
}
- 更多解法:合并区间算法