(leetcode)力扣100 14合并区间(差分/排序)

题目

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。

数据范围

1 <= intervals.length <= 104

intervals[i].length == 2

0 <= starti <=endi <= 104

测试用例

示例1

java 复制代码
输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].

示例2

java 复制代码
输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。

示例3

java 复制代码
输入:intervals = [[4,7],[1,4]]
输出:[[1,7]]
解释:区间 [1,4] 和 [4,7] 可被视为重叠区间。

题解1(博主思路,差分,时间复杂度(max(O(N),O(M)))

java 复制代码
class Solution {
    public static int b[]; 

    public int[][] merge(int[][] intervals) {
        // 1. 初始化差分数组
        b = new int[20005]; 
        

        List<int[]> list = new ArrayList<>();

        int n = intervals.length;
        int tn = n;
        int ti = 0;
        
        int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE; 

        // 2. 差分处理 
        while(tn-- != 0){
            int l = intervals[ti][0] * 2; // 二倍坐标
            int r = intervals[ti][1] * 2;
            
            b[l]++;
            b[r+1]--;
            ti++;
            
            min = Math.min(min, l);
            max = Math.max(max, r);
        }

        // 3. 计算前缀和
        for(int i = min; i <= max + 1; i++){
            if(i>=1)
            b[i] += b[i-1];
        }

        // 4. 收集结果
        int tl = min;
        for(int i = min; i <= max + 1; i++){
            // 如果 b[i] 归零,说明一段连续区间结束了
            if(b[i] == 0 && i - tl > 0){
                list.add(new int[]{tl / 2, (i - 1) / 2});
                tl = i + 1;
            } else if(b[i] == 0 && i - tl <= 0){
                tl = i + 1;
            }
        }

        return list.toArray(new int[list.size()][]);
    }
}

题解2(官方题解,时间复杂度O(nlogn))

java 复制代码
class Solution {
    public int[][] merge(int[][] intervals) {
        if (intervals.length == 0) {
            return new int[0][2];
        }
        Arrays.sort(intervals, new Comparator<int[]>() {
            public int compare(int[] interval1, int[] interval2) {
                return interval1[0] - interval2[0];
            }
        });
        List<int[]> merged = new ArrayList<int[]>();
        for (int i = 0; i < intervals.length; ++i) {
            int L = intervals[i][0], R = intervals[i][1];
            if (merged.size() == 0 || merged.get(merged.size() - 1)[1] < L) {
                merged.add(new int[]{L, R});
            } else {
                merged.get(merged.size() - 1)[1] = Math.max(merged.get(merged.size() - 1)[1], R);
            }
        }
        return merged.toArray(new int[merged.size()][]);
    }
}

思路

这道题相对来说比较简单,数据集量少,规模小,直接排序遍历(O(nlogn))就能满足时间复杂度,唯一就是需要处理一下合并的逻辑关系,因为只有重叠才合并而并非相邻,所以需要者一点,但并不难。

但如果这道题数据量大应该如何处理呢,博主的思路是差分(不知道差分的朋友可以看一下我之前的博客),可以在O(n)的时间复杂度度数据进行处理,然后遍历一遍数组即可,但同样需要注意,由于重叠才合并的关系,我们不能直接使用处理后的差分数组b,我们需要做一点小处理。也就是对所有范围*2,例如1-4与5-6,乘以2后就会被拉开,变为2-8,10-12,不再相邻,可以解决重叠问题。

相关链接

https://blog.csdn.net/qq_62235017/article/details/136778476?spm=1011.2415.3001.5331

相关推荐
leiming62 小时前
C++ 02 函数模板案例
开发语言·c++·算法
自然常数e3 小时前
深入理解指针(6)
c语言·数据结构·算法·visual studio
Xの哲學3 小时前
Linux VxLAN深度解析: 从数据平面到内核实现的全面剖析
linux·服务器·算法·架构·边缘计算
TL滕3 小时前
从0开始学算法——第十八天(分治算法练习)
笔记·学习·算法
月明长歌3 小时前
【码道初阶】【LeetCode 958】判定完全二叉树:警惕 BFS 中的“管中窥豹”陷阱
算法·leetcode·宽度优先
CodeAmaz4 小时前
Java 垃圾回收(GC)算法详解
java·jvm·算法·垃圾回收算法
一直都在5724 小时前
数据结构入门:二叉排序树的构建与相关算法
数据结构·算法
_Minato_4 小时前
数据结构知识整理——复杂度的计算
数据结构·经验分享·笔记·算法·软考
listhi5204 小时前
针对燃油运输和车辆调度问题的蚁群算法MATLAB实现
前端·算法·matlab