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

题目

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

数据范围

1 <= intervals.length <= 104

intervalsi.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

相关推荐
圣保罗的大教堂14 小时前
leetcode 3043. 最长公共前缀的长度 中等
leetcode
码之气三段.14 小时前
牛客周赛 Round 145-E(写了200行的史山)
算法·深度优先
Hwang25215 小时前
Attention-04-decoder部分
算法
devilnumber15 小时前
HAProxy 重点精讲 + 背诵记忆点(面试速记版)
面试·职场和发展
计算机安禾15 小时前
【算法分析与设计】第13篇:最小生成树:Prim算法与Kruskal算法的比较研究
大数据·人工智能·算法
vortex515 小时前
国密(商用密码)算法核心参数速查
算法·密码学
wuweijianlove16 小时前
算法中的记忆化思想与重复子问题优化的技术5
算法
小江的记录本16 小时前
【JVM虚拟机】垃圾回收GC:垃圾判定算法:引用计数法、可达性分析算法(附《思维导图》+《面试高频考点清单》)
java·jvm·后端·python·算法·spring·面试
jiayong2316 小时前
智能体常见面试问题及详细解答
ai·面试·职场和发展·智能体·vibe coding
Hello.Reader17 小时前
算法基础(十四)—— 随机化快速排序为什么平均表现很好
算法