LeetCode刷题之合并区间

137 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。


题目描述

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

思路1-标记
  • 使用count记录区间的长度.

  • 计算公式: count = 1 + end - start;

  • 将区间[start, end] 得出的count放入标记数组flag中,start是索引,count是值, 如果有重复的start,放入更大的count。

  • 遍历标记数组,获取区间,设置一个右边界指针,遍历时检测是否出现更大的边界值,有则替换。

  • 思路清晰,速度超快

  • 时间复杂度:O(n + m) n 原数组长度, m 标记数组长度(总区间内最大值加一)

  • 空间复杂度:O(m)

class Solution {
    public int[][] merge(int[][] intervals) {
        int max = -1;        //生成标记数组的最大索引
        for (int[] interval : intervals) {
            if (max < interval[1]) {
                max = interval[1];
            }
        }
        int[] flag = new int[++max];  //标记数组
        int start, end, count;
        for (int[] interval : intervals) {
            start = interval[0];
            end = interval[1];
            count = 1 + end - start;
            if (flag[start] == 0) {
                flag[start] = count;
            } else if (flag[start] < count) {
                flag[start] = count;
            }
        }
        //遍历flag,获取区间
        int index = 0, pos = 0, right;
        while (index < max) {
            if (flag[index] > 0) {
                start = index;
                right = start + flag[index];          //右边界 不包含
                for (int i = start + 1; i < right; i++) {
                    if (flag[i] != 0 && i + flag[i] > right) { //替换右边界
                        right = i + flag[i];
                    }
                }
                intervals[pos][0] = start;
                intervals[pos][1] = right - 1;
                pos++;
                index = right;
            } else {
                index++;
            }
        }
        int[][] res = new int[pos][2];
        System.arraycopy(intervals, 0, res, 0, pos);

        return res;
    }
}

思路2-双队列
class Solution {
    public int[][] merge(int[][] intervals) {
        if(intervals.length==0){
            return intervals;
        }
        Arrays.sort(intervals,(i, j) -> Integer.compare(i[0],j[0]));
        List<int[]> inQueue = new LinkedList<>();
        Collections.addAll(inQueue,intervals);
        List<int[]> outQueue = new LinkedList<>();
        while (inQueue.size()>1){
            int[] i = inQueue.remove(0);
            int[] j = inQueue.remove(0);
            if(i[0]==j[0]){
                if(i[1]>=j[1]){
                    inQueue.add(0,i);
                }else{
                    inQueue.add(0,j);
                }
            }else{
                if(i[1]<j[0]){
                    outQueue.add(i);
                    inQueue.add(0,j);
                }else{
                    if(i[1]>=j[1]){
                        inQueue.add(0,i);
                    }else{
                        inQueue.add(0,new int[]{i[0],j[1]});
                    }
                }
            }
        }
        outQueue.add(inQueue.get(0));
        return outQueue.toArray(new int[][]{});
    }
}