56. 合并区间

alt

方法一:排序+遍历

class Solution {
    public int[][] merge(int[][] intervals) {
        int n = intervals.length;
        //按照区间的左侧位置排列数组
        Arrays.sort(intervals, (v1, v2) -> (v1[0] - v2[0]));
        int[][] res = new int[n][2];
        int idx = -1;
        //遍历数组
        for (int[] interval : intervals) {
            // 如果结果数组是空的,或者当前区间的起始位置 > 结果数组中最后区间的终止位置
            // 则不合并,直接将当前区间加入结果数组。
            if (idx == -1 || res[idx][1] < interval[0]) {
                res[++idx] = interval;
            } else {
                //反之,将区间合并入之前加入的区间
                res[idx][1] = Math.max(res[idx][1], interval[1]);
            }
        }
        return Arrays.copyOf(res, idx + 1);
    }
}

方法二:位图 bitSet

  • 位图实现了一种直观的想法:开一个大数组,遍历所有区间,每个区间的每一个数对应的大数组索引位置++,数组中不为零的区间段,即为合并之后的答案。
class Solution {
    public int[][] merge(int[][] intervals) {
        BitSet bitSet = new BitSet();
        int max = 0;
        for (int[] interval : intervals) {
            //[1,4]&[5,6]在数轴上是不连续的,但是BitSet上却是连续的,
            //所以进行乘2,使他们从BitSet上看也不是连续的
            int temp = interval[1] * 2 + 1;
            //BitSet 的set方法,将[left, right) 区间置为true/false
            bitSet.set(interval[0] * 2, temp, true);
            //找出最大值,方便之后遍历
            max = temp >= max ? temp : max;
        }

        int index = 0, count = 0;
        while (index < max) {
            //nextSetBit(index):找出从index开始,第一个为true的索引
            int start = bitSet.nextSetBit(index);
            //nextClearBit(start):找出从start开始,第一个为false的索引
            int end = bitSet.nextClearBit(start);
            //映射到原区间
            int[] item = {start / 2, (end - 1) / 2};
            //count表示最终的区间数目,同时也充当了索引
            intervals[count++] = item;
            //index指向end,继续遍历
            index = end;
        }
        int[][] ret = new int[count][2];
        for (int i = 0; i < count; i++) {
            ret[i] = intervals[i];
        }

        return ret;
    }
}

BitSet类常用方法