算法题12:合并取件

题目描述:

以数组 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] 可被视为重叠区间。

 

思路:

这个题开始写了一版,没过,然后看了一点指引提示先排序,改了下就过了~

我的版本:

class Solution:
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:
        intervals.sort(key=lambda x:x[0])
        res = []
        if len(intervals) == 1:
            return intervals
        i = 0
        initial_start = intervals[0][0]
        initial_end = intervals[0][1]
        while i < (len(intervals) - 1):
            i+=1
            cureent_start = intervals[i][0]
            cureent_end = intervals[i][1]
            
            if initial_end >= cureent_start:
                initial_end = max(cureent_end, cureent_start, initial_end)
            else:
                res.append([initial_start, initial_end])
                initial_start, initial_end = cureent_start, cureent_end
            if i == len(intervals) - 1:
                res.append([initial_start, initial_end])
        # 
        return res
        

结果:

 

 

看了结题思路:

按照左端点排序:以示例1为例,输入为[1,3],[2,6],[8,10],[15,18] 这四个取件

为方便合并,把取件按照左端点从小到大排序,排序后,就知道了第一个合并取件的左端点,即intervals[0][0] = 1

第一个合并取件的左端点目前只确定是大于等于intervals[0][1] = 3,但具体是多少还得向右遍历才知道。

 

具体算法:

1、把intervals[0]加入答案。答案的最后一个取件表示当前正在合并的取件

2、遍历到intervals[1] = [2,6],由于左端点2不超过当前合并区间的右端点3,可以合并。

    由于右端点6>3,那么更新当前合并取件的右端点为6。注意,由于我们已经你找左端点排序,

    所以intervals[1]的左端点2必然大于等于合并取件的左端点,所以无需更新当前合并取件的左端点。

 3、遍历到intervals[2] = [8,10],由于左端点8大于当前合并区间的右端点6,无法合并(两个区间不相交)。再次利用区间按照左端点排序的性质,更后面的区间的左端点也大于6,

    无法与当前合并取件相交,所以当前合并区间[1,6]就固定下来了,把新的合并取件[8,10]加入答案。

4、遍历到intervals[3] = [15, 18],由于左端点15大于当前合并取件的右端点10,无法合并(区间不相交),我们找到了一个新的合并区间[15, 18]加入答案。

上述算法同时说明,按照左端点排序后,合并区间一定是intervals中的连续子数组。

 

python:

class Solution:
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:
        intervals.sort(key=lambda x:x[0]) # 按照左端点从小到大排序
        res = []
        for i in intervals:
            if res and i[0] <= res[-1][1]: # 可以合并
                res[-1][-1] = max(res[-1][1], i[1]) # 更新右端点最大值
            else: # 不相交,无法合并
                res.append(i) # 新的合并区间
        # 
        return res
        

 

java

class Solution {
    public int[][] merge(int[][] intervals) {
        Arrays.sort(intervals, (p, q) -> p[0] - q[0]); // 按照左端点从小到大排序
        List<int[]> ans = new ArrayList<>();
        for (int[] p : intervals){
            int m = ans.size();
            if (m > 0 && p[0] <= ans.get(m - 1)[1]) { // 可以合并
                ans.get(m - 1)[1] = Math.max(ans.get(m-1)[1], p[1]); // 更新右端点最大值
            } else {// 不相交,无法合并
                ans.add(p); // 新的合并取件
            }
        }
        return ans.toArray(new int[ans.size()][]);
    }

}

 

:

 

posted @ 2025-05-25 10:00  夏晓旭  阅读(15)  评论(0)    收藏  举报