多个数组合并区间

问题描述
以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
例如:
输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
先给大家贴上我自己的代码
我的想法是先将所有的数据按照区间开始由小到大排序,自己根据归并排序的思路写了一个区间的排序

/**
* 根据归并排序的思想进行排序,将待排序数组拆分后,对比合并成新的数组
*/
public static int[][] arraySort(int[][] intervals){
        if (intervals.length==1){
            return intervals;
        }
        int mid = intervals.length >> 1;
        int[][] left = Arrays.copyOfRange(intervals,0,mid);
        int[][] right = Arrays.copyOfRange(intervals,mid,intervals.length);
        return combineArray(arraySort(left),arraySort(right));
    }
	/**
	* 数组合并,成新的有序数组
	*/
    public static int[][] combineArray(int[][] leftArray,int[][] rightArray){
        int[][] result = new int[leftArray.length+rightArray.length][2];
        int leftIndex = 0;
        int rightIndex = 0;
        for (int i = 0 ; i< result.length;i++){
            if (leftIndex>= leftArray.length){
                // 左侧的数据已经遍历完毕
                result[i] = rightArray[rightIndex++];
            } else if(rightIndex>= rightArray.length){
                // 右侧数据已经遍历完毕
                result[i] = leftArray[leftIndex++];
            } else if(leftArray[leftIndex][0]<rightArray[rightIndex][0]){
                // 左侧的范围小
                result[i] = leftArray[leftIndex++];
            } else if(leftArray[leftIndex][0]>=rightArray[rightIndex][0]){
                // 右侧的范围小
                result[i] = rightArray[rightIndex++];
            }
        }
        return result;
    }
    public int[][] merge(int[][] intervals) {
    	// 调用自己的排序算法
        intervals = arraySort(intervals);
        // 创建新的列表,存储排序区间
        List<int[]> list = new ArrayList<>();
        // 循环时候,默认区间为第一个区间
        for (int i = 0 ;i < intervals.length;){
            int[] result = new int[2];
            int[] temp1 = intervals[i];
            // 由于排序后的区间是有序的,所以开始第一个区间的开始就是合并区间的开始
            result[0] = temp1[0];
            int end = temp1[1];
            while (i < intervals.length - 1) {
            	// 向后延申寻找,直到没有重合的区间
                int[] temp2 = intervals[i + 1];
                if(end >= temp2[0]) {
                	// 寻找合并区间的结束区间
                    end = Math.max(end,temp2[1]);
                    // 同时for循环向后移动,不会再次对比已经合并的数据
                    i++;
                } else {
                    break;
                }
            }
            // 循环结束,意味这本轮元素区间合并完成
            result[1] = end;
            list.add(result);
            // 由于每次对比都是将后一个与i进行对比,因此,如果后一个不在区间内的同时,for循环
            // 元素后移,到下一个元素
            i++;
        }
        // 返回结果
        return list.toArray(new int[list.size()][2]);
    }

运行结果不尽如人意
在这里插入图片描述
找了一个案例参考了一下最后发现,排序部分消耗了大量的时间

public int[][] merge(int[][] intervals) {
        if(intervals == null || intervals.length<=1)
            return intervals;
        // 排序部分修改为Arrays.sort()方法,果然提升了不少
        // 革命尚未成功,同志仍需努力啊
        Arrays.sort(intervals,new Comparator<int[]>(){
            @Override
            public int compare(int[] a,int[] b){
                return a[0]-b[0];
            }
        });
        List<int[]> list = new ArrayList<>();
        for (int i = 0 ;i < intervals.length;){
            int[] result = new int[2];
            int[] temp1 = intervals[i];
            result[0] = temp1[0];
            int end = temp1[1];
            while (i < intervals.length - 1) {
                int[] temp2 = intervals[i + 1];
                if(end >= temp2[0]) {
                    end = Math.max(end,temp2[1]);
                    i++;
                } else {
                    break;
                }
            }
            i++;
            result[1] = end;
            list.add(result);
        }
        return list.toArray(new int[list.size()][2]);
    }

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值