(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

相关推荐
Lsir10110_2 分钟前
【力扣hot100】矩阵题通关复盘
算法·leetcode·矩阵
退休倒计时3 分钟前
【每日一题】LeetCode 207. 课程表 TypeScript
算法·leetcode·typescript
稚南城才子,乌衣巷风流24 分钟前
树的重心:概念、性质与算法详解
算法·深度优先·图论
不会就选b28 分钟前
算法日常・每日刷题--<哈希>1
算法·哈希算法
zander25836 分钟前
LeetCode 207. 课程表
算法·深度优先
萌动的小火苗38 分钟前
深度学习中的损失函数与优化算法基础知识
人工智能·深度学习·算法
happyprince40 分钟前
02_OpenCodeReview 具体观:八种算法机制与背后的论文谱系
算法
变量未定义~43 分钟前
图论+动态规划——魔法阵
算法
大爱编程♡1 小时前
C++基础-类和对象
c++·算法
ysa0510301 小时前
【板子】费用流
算法·深度优先·图论