算法练习帖--21--合并区间(Java)

合并区间

一、题目描述:

给出一个区间的集合,请合并所有重叠的区间。
(题目来源:力扣(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] 可被视为重叠区间。

二、解决方法:

  1. 优化后的希尔排序(可以选择其它的排序方法)+合并区间
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][]);
	}
}

  1. 更多解法:合并区间算法

猜你喜欢

转载自blog.csdn.net/Inmaturity_7/article/details/110560752