1题目描述
2思路
- 在合并区间之前,需要对所有的区间按照区间第一个元素进行排序,这样可以保证已经合并的各个区间之后不会再包含其他区间,或者被其他区间包含;
- 首先自己进行一下排序练习,回顾冒泡排序和选择排序,详见3.1使用排序算法对区间进行排序;
- 在合并时,核心思想就是:准备一个空的列表,每次合并都取列表中最后一个区间去和当前待加入的区间进行合并;因为区间已经排过序了,所以列表中非最后一个元素与当前待加入的区间肯定是没有重叠的;详见3.2合并区间;
3实现
3.1使用排序算法对区间进行排序
Anchor1
- 冒泡排序和选择排序的动态执行过程详见:冒泡排序和选择排序_选择排序和冒泡排序-CSDN博客;
3.1.1冒泡排序
-
核心思想:
- 两层循环:外层循环控制趟数,内层循环控制每一趟比较的次数;
- 两两比较,即时交换
-
应用到区间排序上,代码如下:
from typing import Listclass Solution:def merge1(self, intervals: List[List[int]]) -> List[List[int]]:# 先排序,按照每个区间的左侧数值升序排序,使用冒泡排序# 外层循环控制排序的轮数for i in range(0, len(intervals) - 1):# 内层循环控制每一轮的比较次数for j in range(0, len(intervals) - 1 - i):# 相邻元素两两比较,升序排列if intervals[j][0] > intervals[j + 1][0]:intervals[j], intervals[j + 1] = intervals[j + 1], intervals[j]print("冒泡排序结果:", intervals) # 主函数 if __name__ == '__main__':# intervals = [[1,3],[2,6],[8,10],[15,18]]# intervals = [[1, 3], [8, 10], [15, 18], [2, 6]]intervals = [[1, 3], [16, 10], [15, 18], [2, 6]]solution = Solution()solution.merge1(intervals)# print(result)
3.1.2选择排序
-
核心思想:
- 两层循环:外层循环控制轮数(或者说固定住然后待比较的数),内层循环控制每一轮比较的次数(或者说控制当前参与比较的数)
- 每一轮,固定住某一个数,然后看之后的数是否比这个数大(小),如果是,则更新最大(小)的索引;最后完成交换;
-
应用到区间排序上,代码如下:
from typing import Listclass Solution:def merge2(self, intervals: List[List[int]]) -> List[List[int]]:# 先排序,按照每个区间的左侧数值升序排序,使用选择排序for i in range(0, len(intervals) - 1):min_index = i # 记录最小值的索引for j in range(i + 1, len(intervals)):if intervals[j][0] < intervals[min_index][0]:min_index = j # 更新最小值的索引if min_index != i:# 最小值不是当前i索引对应的值,交换intervals[i], intervals[min_index] = intervals[min_index], intervals[i]print("选择排序结果:", intervals)# 主函数 if __name__ == '__main__':# intervals = [[1,3],[2,6],[8,10],[15,18]]# intervals = [[1, 3], [8, 10], [15, 18], [2, 6]]# intervals = [[1, 3], [2, 10], [15, 18], [2, 6]]intervals = [[1, 3], [2, 5], [15, 18], [2, 6]]solution = Solution()solution.merge2(intervals)# print(result)
3.2合并区间
Anchor2
-
主要思路:准备一个空列表
sorted_list
,比较前一个区间的右侧数值和当前区间的左侧数值,如果前一个区间的右侧数值小于当前区间的左侧数值,则两个区间不重叠,直接添加进来;否则重叠,需要更新sorted_list
中最后一个区间的右侧数值; -
代码如下:
from typing import Listclass Solution:def merge1(self, intervals: List[List[int]]) -> List[List[int]]:# 先排序,按照每个区间的左侧数值升序排序,使用冒泡排序# 外层循环控制排序的轮数for i in range(0, len(intervals) - 1):# 内层循环控制每一轮的比较次数for j in range(0, len(intervals) - 1 - i):# 相邻元素两两比较,升序排列if intervals[j][0] > intervals[j + 1][0]:intervals[j], intervals[j + 1] = intervals[j + 1], intervals[j]print("冒泡排序结果:", intervals)# 合并区间sorted_list = []for item in intervals:# 空列表被视为False,非空列表被视为Trueif not sorted_list or sorted_list[-1][-1] < item[0]:# 比较前一个区间的右侧数值和当前区间的左侧数值,如果前一个区间的右侧数值小于当前区间的左侧数值,则两个区间不重叠sorted_list.append(item)else:# 重叠则需要更新sorted_list中最后一个区间的右侧数值sorted_list[-1][1] = max(sorted_list[-1][-1], item[1])return sorted_list# 主函数 if __name__ == '__main__':# intervals = [[1,3],[2,6],[8,10],[15,18]]intervals = [[1, 3], [8, 10], [15, 18], [2, 6]]# intervals = [[1, 3], [2, 10], [15, 18], [2, 6]]# intervals = [[1, 3], [2, 5], [15, 18], [2, 6]]solution = Solution()sorted_list = solution.merge1(intervals)print("合并区间结果:", sorted_list)# solution.merge2(intervals)# print(result)
-
在力扣上执行,提示超出时间限制,可见这里使用冒泡排序的时候,两层循环的嵌套增加了算法的复杂度;
3.3排序算法修改
- 前面是自己实现了冒泡排序或者选择排序,其实python中的列表有封装好的排序算法
-
这里使用封装好的排序算法,即list中封装的
sort
函数:- 只需执行:
intervals.sort(key=lambda x: x[0])
;key用于指定一个函数,这个函数会被应用到列表中的每一个元素上,获取用于排序的键; - 关于此函数:
- 只需执行:
-
因此,最终的合并区间的算法代码为:
from typing import Listclass Solution:def merge1(self, intervals: List[List[int]]) -> List[List[int]]:# 先排序,按照每个区间的左侧数值升序排序intervals.sort(key=lambda x: x[0])# 合并区间sorted_list = []for item in intervals:# 空列表被视为False,非空列表被视为Trueif not sorted_list or sorted_list[-1][-1] < item[0]:# 比较前一个区间的右侧数值和当前区间的左侧数值,如果前一个区间的右侧数值小于当前区间的左侧数值,则两个区间不重叠sorted_list.append(item)else:# 重叠则需要更新sorted_list中最后一个区间的右侧数值sorted_list[-1][1] = max(sorted_list[-1][-1], item[1])return sorted_list# 主函数 if __name__ == '__main__':# intervals = [[1,3],[2,6],[8,10],[15,18]]intervals = [[1, 3], [8, 10], [15, 18], [2, 6]]# intervals = [[1, 3], [2, 10], [15, 18], [2, 6]]# intervals = [[1, 3], [2, 5], [15, 18], [2, 6]]solution = Solution()sorted_list = solution.merge1(intervals)print("合并区间结果:", sorted_list)# solution.merge2(intervals)# print(result)
-
然后,就不会超出时间限制了: