1题目描述
2思路
- 在合并区间之前,需要对所有的区间按照区间第一个元素进行排序,这样可以保证已经合并的各个区间之后不会再包含其他区间,或者被其他区间包含;
- 首先自己进行一下排序练习,回顾冒泡排序和选择排序,详见3.1使用排序算法对区间进行排序;
- 在合并时,核心思想就是:准备一个空的列表,每次合并都取列表中最后一个区间去和当前待加入的区间进行合并;因为区间已经排过序了,所以列表中非最后一个元素与当前待加入的区间肯定是没有重叠的;详见3.2合并区间;
3实现
3.1使用排序算法对区间进行排序
Anchor1
- 冒泡排序和选择排序的动态执行过程详见:冒泡排序和选择排序_选择排序和冒泡排序-CSDN博客;
3.1.1冒泡排序
-
核心思想:
- 两层循环:外层循环控制趟数,内层循环控制每一趟比较的次数;
- 两两比较,即时交换
-
应用到区间排序上,代码如下:
from typing import List class 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 List class 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 List class 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,非空列表被视为True if 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 List class 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,非空列表被视为True if 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)
-
然后,就不会超出时间限制了: