leetcode笔记之[56. 合并区间]

54 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第9天,点击查看活动详情

合并区间

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

 

示例 1:

输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3][2,6] 重叠, 将它们合并为 [1,6]

示例 2:

输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。

提示:

  • 1 <= intervals.length <= 10^4
  • intervals[i].length == 2
  • 0 <= starti <= endi <= 10^4

解题思路

  • 因为最终要执行合并动作,为了保证最终遍历的时间复杂度为O(n),需要先根据子区间的左边界排序
  • 排序完成后,从左往后遍历子区间
    • 如果结果集中最后一个interval小于当前遍历的interval,执行两个子区间的合并动作,并替换结果集中的最后一个interval
    • 否则说明区间不连续,直接把当前的interval加在结果集中即可

代码实现

class Solution {
    public int[][] merge(int[][] intervals) {
        
        //排序:按子数组左区间排序
        Arrays.sort(intervals, new Comparator<int[]>(){
            public int compare(int[] interval1, int[] interval2) {
                return interval1[0] - interval2[0];
            }
        });
        List<int[]> result = new ArrayList<>();
        //第一个interval先放进结果集中
        result.add(intervals[0]);
        //遍历即可
        int[] current;
        int[] prev;
        for(int i = 1; i < intervals.length; i++){
            current = intervals[i];
            prev = result.get(result.size() - 1);
            //前一个interval的右区间 > 当前interlval的左区间
            if(prev[1] >= current[0]){
                result.set(result.size() - 1,this.doMerge(prev,intervals[i]));
            }else{
                result.add(current);
            }
        }
        return result.toArray(new int[result.size()][]);
    }

    private int[] doMerge(int[] prev, int[] current){
        int left = prev[0];
        int right = Math.max(prev[1],current[1]);
        return new int[]{left,right};
    }
}

参考

O(n),一个易于理解的效率还可以的旁门左道的思路 - 合并区间 - 力扣(LeetCode)

java手撕快速排序算法,代码稍多,思路清晰,简单易懂 - 合并区间 - 力扣(LeetCode)