(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

相关推荐
Jerry2 分钟前
LeetCode 28. 找出字符串中第一个匹配项的下标
算法
Jerry2 小时前
LeetCode 459. 重复的子字符串
算法
海石5 小时前
1500分的题目,确实有实力,不过还是我略胜一筹
算法·leetcode
海石5 小时前
【记忆化搜索】条条大路通AC,走好适合你的那一条,走到后再考虑走得快
算法·leetcode
Jerry7 小时前
LeetCode 151. 反转字符串中的单词
算法
咖啡星人k9 小时前
从Vibe Coding到Prompt Engineering:AI编程的新技能树
面试·职场和发展·ai编程
a1117769 小时前
LM 算法迭代过程动画演示(SLAM)
算法
头茬韭菜9 小时前
Context 的生死抉择:四层压缩、截断算法与 Session Memory
算法·ai
Jerry9 小时前
LeetCode 541. 反转字符串 II
算法
Jerry10 小时前
LeetCode 344. 反转字符串
算法