632. 最小区间
你有 k 个升序排列的整数数组。找到一个最小区间,使得 k 个列表中的每个列表至少有一个数包含在其中。
我们定义如果 b-a < d-c 或者在 b-a == d-c 时 a < c,则区间 [a,b] 比 [c,d] 小。
示例 1:
输入:[[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] 中。
注意:
给定的列表可能包含重复元素,所以在这里升序表示 >= 。
1 <= k <= 3500
-105 <= 元素的值 <= 105
对于使用Java的用户,请注意传入类型已修改为List<List>。重置代码模板后可以看到这项改动。
这道题目我首先想到的就是76. 最小覆盖子串这道题的解法,使用滑动窗口进行求最小包含区间。但是这道题目在原始的数据中是多个列表的存在形式。所以在确定每一个列表都有一个值得时候,需要对每一个列表增加一个列表属性的标签。
增加属性标签就是将一维的列表增至二维,第一维为属性,第二维为数值。再将每一组二维数据合并在一起,具体的实现代码为:
for i in range(k):#k个列表
res += [[i, item] for item in nums[i]]#对每一个列表的内的数组增维
增维之后我们再对数据的第二维进行一个递增排序,这样就和之前的76题类似了。
- 建立两个字典,一个为目标需要的字典need,包含了key,val。key:需要的标签名称,val:该类标签需要的个数。由于本次需要所有的k个列表内的值,都出现依次,所以可以直接复制,key = i , val = 1。
- 建立win窗口字典,包含的是窗口内的标签种类以及数量。当win满足need的最低要求时,可以加入输出。这里的最低要求使用的是valid表示,每当win[i] 增加一个之后,win[i] == 1,的时候,valid就会加一,之后win[i]再继续增加,超过一,虽然会继续计数,但是valid值是不会增加,因为已经满足最小匹配了。
- 当valid 的个数等于 k的个数的时候,说明这个区间内是满足至少每个列表有一个数的。为了求一个最优的区间,这个时候需要缩小左边界。缩小左边界的时候,如果最左边对应的字典值win[ i ] == 1,那么在缩小的过程中间,win[ i ] 就会变成0,此时的valid个数也会减一。
- 每次得到valid == k的时候,我们要计算一下此时的区间长度,每次更新找到一个最优的区间长度。
class Solution:
def smallestRange(self, nums: List[List[int