题目地址(632. 最小区间)
题目描述
你有 k 个 非递减排列 的整数列表。找到一个 最小 区间,使得 k 个列表中的每个列表至少有一个数包含在其中。
我们定义如果 b-a < d-c 或者在 b-a == d-c 时 a < c,则区间 [a,b] 比 [c,d] 小。
示例 1:
输入:nums = [[4,10,15,24,26], [0,9,12,20], [5,18,22,30]]
输出:[20,24]
解释:
列表 1:[4, 10, 15, 24, 26],24 在区间 [20,24] 中。
列表 2:[0, 9, 12, 20],20 在区间 [20,24] 中。
列表 3:[5, 18, 22, 30],22 在区间 [20,24] 中。
示例 2:
输入:nums = [[1,2,3],[1,2,3],[1,2,3]]
输出:[1,1]
提示:
nums.length == k
1 <= k <= 3500
1 <= nums[i].length <= 50
-105 <= nums[i][j] <= 105
nums[i] 按非递减顺序排列
前置知识
公司
- 暂无
思路
关键点
代码
- 语言支持:Python3
Python3 Code:
class Solution:
def smallestRange(self, nums: List[List[int]]) -> List[int]:
# 采用多路回归的方式
l,r = -float('inf'),float('inf')
# 构建小根堆
h = [(row[0],i,0) for i,row in enumerate(nums)]
heapq.heapify(h)
max_v = max([row[0] for row in nums])
# 思路:
"""
采用多路归并的思想,首先取二维数组的第一列元素,记住每个元素的行、列,组成一个小根堆,从而可以维护一个小区间
这个区间的最小值就是堆顶,最大值可以用一个变量表示
现在考虑如何进行多路归并,基本思想就是取出区间最小值后,在这一列继续向下取值
为什么选择在最小值后面继续取值?
前提:二维数字的每一行都是非递减的
那么在已经有一个区间的前提下,移动左区间是比移动其他区间中的任何值更加能保证区间可以hold所有值
"""
while True:
min_v, row, col = heapq.heappop(h)
if max_v - min_v < r - l:
l,r = min_v, max_v
if col == len(nums[row]) - 1: return l,r
heapq.heappush(h,(nums[row][col+1],row,col+1))
max_v = max(nums[row][col+1],max_v)
复杂度分析
令 n 为数组长度。
- 时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
- 空间复杂度: O ( n ) O(n) O(n)