算法题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()][]); } }
:

浙公网安备 33010602011771号