LC56 为你把坑都踩了的线段合并问题|刷题打卡

895 阅读1分钟

本系列使用IDEA+LEETCODE EDITOR插件,题目描述统一英文题目链接
一、题目描述:

//Given an array of intervals where intervals[i] = [starti, endi], merge all ove
//rlapping intervals, and return an array of the non-overlapping intervals that co
//ver all the intervals in the input. 
//
// 
// Example 1: 
//
// 
//Input: intervals = [[1,3],[2,6],[8,10],[15,18]]
//Output: [[1,6],[8,10],[15,18]]
//Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6].
// 
//
// Example 2: 
//
// 
//Input: intervals = [[1,4],[4,5]]
//Output: [[1,5]]
//Explanation: Intervals [1,4] and [4,5] are considered overlapping.
// 
//
// 
// Constraints: 
//
// 
// 1 <= intervals.length <= 104 
// intervals[i].length == 2 
// 0 <= starti <= endi <= 104 

二、思路分析:
首先读题,给出一组区间,要求进行交叉区间的合并,此处切记只合并交叉不合并相邻
一开始很容易被这道题迷惑,以为这不就是E难度的么,等到你开始编码和调试就会感受到这道题背后的恶意。
恶意1: 这道题有说区间的顺序么?并没有,所以可能你处理了[1,3],[2,4],[5,8]3个区间时已经往返回值塞了[1,4],[5,8] 2个区间,这时来了一个[1,10],你怎么办?所以这道题的基本思路就是排序,不然无法处理历史数据。 恶意2: 你说你就头铁(比如我)就不想用排序,于是重新思考这道题发现可以用计数排序的思路。因为题意给出了线段长度范围在[0,104],虽然用计数排序写出的代码在生产不可用,还是想试试,但是依然发现很难处理没有排序的区间合并问题。尤其是存在[2,2]这种只有一个数字的区间的情况下。
所以能做出来是第一优先级,先别管暴力还是你不屑的排序等等方式先写出来一个解,如果做出来了面试官再让你优化是后面的事,做不做得出来是另一回事了,这个才是这期的重点内容

三、AC 代码:

public int[][] merge(int[][] intervals) {
    // 以左区间进行排序
    Arrays.sort(intervals, Comparator.comparingInt(a -> a[0]));
    // 初始化长度为最大可能,就是一个都不能合并
    int[][] res = new int[intervals.length][2];
    // -1表示一个都没合并
    int index = -1;
    for (int[] interval : intervals) {
        // 如果前面没有区间或者当前区间不在前面区间范围内
        if(index == -1 || interval[0] > res[index][1]){
            res[++index] = interval;
        }else{
            // 合并区间
            // 因为已经排过序了,只需要判断哪个的右侧大即可
            res[index][1] = Math.max(res[index][1],interval[1]);
        }
    }
    // 只返回有效长度
    return Arrays.copyOf(res,index + 1);
}
		解答成功:
			执行耗时:11 ms,击败了11.74% 的Java用户
			内存消耗:41.3 MB,击败了30.29% 的Java用户

四、总结:

  1. 没思路时就先写出一个解法再考虑优化。
  2. 不要头铁觉得自己可以独辟蹊径,尤其在面试过程中。
  3. 算法还是要能应用到生产场景的,计数排序并不适合。

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情