描述
合并两个已排序的区间列表,并将其作为一个新的有序区间列表返回。新的区间列表应该通过拼接两个列表的区间并按升序排序。
同一个列表中的区间一定不会重叠。
不同列表中的区间可能会重叠。
区 间 列 表 : 0 ≤ len ( list1 ) , len ( list2 ) ≤ 10000 区间列表:0 \leq \text{len}(\textit{list1}), \text{len}(\textit{list2}) \leq 10000 区间列表:0≤len(list1),len(list2)≤10000
列 表 元 素 : 1 ≤ list1 [ i ] , list2 [ i ] ≤ 1000 列表元素:1 \leq \textit{list1}[i], \textit{list2}[i] \leq 1000 列表元素:1≤list1[i],list2[i]≤1000
样例
样例1
输入: list1 = [(1,2),(3,4)] and list2 = [(2,3),(5,6)]
输出: [(1,4),(5,6)]
解释:
(1,2),(2,3),(3,4) --> (1,4)
(5,6) --> (5,6)
样例2
输入: list1 = [(1,2),(3,4)] 和 list2 = [(4,5),(6,7)]
输出: [(1,2),(3,5),(6,7)]
解释:
(1,2) --> (1,2)
(3,4),(4,5) --> (3,5)
(6,7) --> (6,7)
from typing import (
List,
)
from lintcode import (
Interval,
)
"""
Definition of Interval:
class Interval(object):
def __init__(self, start, end):
self.start = start
self.end = end
"""
class Solution:
"""
@param list1: one of the given list
@param list2: another list
@return: the new sorted list of interval
"""
def merge_two_interval(self, list1: List[Interval], list2: List[Interval]) -> List[Interval]:
# write your code here
if not list1:
return list2
if not list2:
return list1
index1, index2 = 0, 0
ans = []
#now代表list1和list2中将要加入ans的区间
while index1 < len(list1) and index2 < len(list2):
a = list1[index1]
b = list2[index2]
#如果a左端点较小,说明a将被加入ans中,
#所以令now = a,同时将i加一以便后面继续加入
#如果b左端点较小,也类似操作
if a.start <= b.start:
now = a
index1 += 1
else:
now = b
index2 += 1
#如果ans为空,那就直接将区间加进去
#否则将ans末尾的区间与now进行合并
if not ans:
ans.append(now)
else:
self.merge(ans, ans[len(ans) - 1], now)
#如果list1已经全被加进去了,则将list2的区间一个一个merge进ans中
while index2 < len(list2):
self.merge(ans, ans[len(ans) - 1], list2[index2])
index2 += 1
#同上
while index1 < len(list1):
self.merge(ans, ans[len(ans) - 1], list1[index1])
index1 += 1
return ans
#merge函数将ans末尾的区间与now合并后加入ans
def merge(self, ans, last, now):
#如果last与now不相交,那直接将now加进ans即可
#否则直接拓展last的右端点
if last.end < now.start:
ans.append(now)
else:
last.end = max(last.end, now.end)
算法:贪心+双指针
算法思路
用两个指针index1和index2分别指向list1和list2的头部,然后比较两个区间的左端点,挑出左端点较小的,将其与答案中最后一个区间进行比较,如果可以合并则合并,否则就将那个区间加入到答案最后。直到所有区间都被合并或者加入到答案中为止
代码思路
-
先进行特判,若其中一个list为空则直接返回另一个list
-
将两个指针index1和index2分别指向list1和list2的头部,即等于0
-
比较指针指向的两个区间的左端点,取出较小的一个左端点的区间,将其赋值给变量now,并将该指针右移一位
-
将now的左端点与答案list中末尾的右端点比较,若小于末尾右端点则将其合并,即last.end = max(last.end, now.end),否则将now 作为一个独立的区间加入到答案list中
-
重复3、4两个步骤,直到其中一个指针指向末尾
-
若有指针还未指向末尾,将指针不断右移并将其指向的区间加入或合并至答案中(判断条件与方法与第四步相同)
复杂度分析
N表示list1的长度,M表示list2的长度
空间复杂度:O(N+M)
时间复杂度:O(N+M)