合并区间问题,采用的方法和滑窗法类似,都是在for循环中动态找到最大值和最小值。
56. 合并区间
逻辑相对比较简单,注意开始要对intervals进行排序。
动态的对比ans[-1][-1]与interval[0]的大小来更改ans[-1][-1]
class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
ans = []
intervals.sort()
for i in intervals:
if not ans or ans[-1][-1] < i[0]:
ans.append(i)
else:
ans[-1][-1] = max(ans[-1][-1],i[1])
return ans
57. 插入区间
在上一题的基础上进一步加深理解,插入区间。
当然,有一种比较简单的方式就是两个区间合并后,按照上面56的方式进行处理。
不过也可以将当前的区间拆分成左中右三份进行处理,原题解
代码如下:
class Solution:
def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:
s, e = newInterval[0], newInterval[1]
left = [i for i in intervals if i[1] < s]
right = [i for i in intervals if i[0] > e]
if left + right != intervals:
s = min(s, intervals[len(left)][0])
e = max(e, intervals[~len(right)][1])
return left + [[s,e]] + right
88. 合并两个有序数组
这道题是个简单题,直接合并sort,或者构造新的list排序两种方式都很容易想出来。但是显然第一种利用了内置函数,肯定不是面试官想要的答案,第二种利用了新的空间,增大了内存占用。
所以,这里想mark一种没有空间复杂度为O(1)的算法,
从后向前进行遍历排序
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
p1 = m - 1
p2 = n -1
p = m + n -1
#最简单的方式,空间复杂度为1,没有增加额外的空间
while p1 >= 0 and p2 >= 0:
if nums1[p1] > nums2[p2]:
nums1[p] = nums1[p1]
p1 -= 1
else:
nums1[p] = nums2[p2]
p2 -= 1
p -= 1
nums1[:p2+1] = nums2[:p2+1]
986. 区间列表的交集
合并区间题目的基本思路,利用一个while循环,并动态地确定每一个区间左右边界即可
class Solution:
def intervalIntersection(self, A: List[List[int]], B: List[List[int]]) -> List[List[int]]:
ans = []
i = j = 0
while i < len(A) and j < len(B):
lo = max(A[i][0],B[j][0])
hi = min(A[i][1],B[j][1])
if lo <= hi:
ans.append([lo,hi])
if A[i][1] < B[j][1]:
i += 1
else:
j += 1
return ans
646. 最长数对链
第一遍没看清楚题目,要明白给出的数对是可以打乱重新排序的。这样一来就简单了很多。
按照数对中的第二个数字进行排序,随后进行首位对比即可。
class Solution:
def findLongestChain(self, pairs: List[List[int]]) -> int:
pairs = sorted(pairs,key = lambda x:x[1])
res = 1
start = pairs[0][1]
for pair in pairs[1:]:
if pair[0] > start:
start = pair[1]
res += 1
return res