(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

相关推荐
Paul_09206 分钟前
golang编程题
开发语言·算法·golang
颜酱11 分钟前
用填充表格法-继续吃透完全背包及其变形
前端·后端·算法
夏秃然14 分钟前
打破预测与决策的孤岛:如何构建“能源垂类大模型”?
算法·ai·大模型
氷泠18 分钟前
课程表系列(LeetCode 207 & 210 & 630 & 1462)
算法·leetcode·拓扑排序·反悔贪心·三色标记法
代码or搬砖21 分钟前
JVM垃圾回收器
java·jvm·算法
老鼠只爱大米23 分钟前
LeetCode算法题详解 15:三数之和
算法·leetcode·双指针·三数之和·分治法·three sum
客卿12323 分钟前
C语言刷题--合并有序数组
java·c语言·算法
2301_8008951024 分钟前
hh蓝桥杯每日一题
职场和发展·蓝桥杯
Qhumaing24 分钟前
C++学习:【PTA】数据结构 7-1 实验6-1(图-邻接矩阵)
c++·学习·算法
菜鸟233号38 分钟前
力扣416 分割等和子串 java实现
java·数据结构·算法·leetcode