【每日算法】最小区间

题目描述


这是 LeetCode 上的 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]

示例 3:

输入:nums = [[10,10],[11,11]]
输出:[10,11]

示例 4:

输入:nums = [[10],[11]]
输出:[10,11]

示例 5:

输入:nums = [[1],[2],[3],[4],[5],[6],[7]]
输出:[1,7]

提示:

nums.length == k
1 <= k <= 3500
1 <= nums[i].length <= 50
-10^5 <= nums[i][j] <= 10^5
nums[i] 按非递减顺序排列

分析题目要求

找到一个区间,要求区间内包括k个列表中每个列表最少一个数字。
首先合并k个列表,保存当前数组所在的数组,并按升序进行排列
[(0,1),(4,0),(5,2),(9,1),(10,0),(12,1),(15,0),(18,2),(20,1),(22,2),(24,0),(26,0),(30,2)]
这样就变成了与76.最小覆盖子串一样的题目了
定义一个窗口,窗口内包括k个列表的索引(0,1,2...k),并且最小值和最大值的差值最小,一直遍历到最后结尾,就找到了满足要求的答案了

代码实现

import collections
class Solution(object):
    def smallestRange(self, nums):
        all_nums=[]
        k=len(nums)
        need=collections.defaultdict(int)
        for i in range(k):
            need[i]+=1
            for j in range(len(nums[i])):
                all_nums.append((nums[i][j],i))
        all_nums=sorted(all_nums,key=lambda x:x[0])
        res=[0,float('inf')]
        i=0
        # print(need)
        for num,f in all_nums:
            # print(num,f)
            if need[f]>0:
                k-=1
            need[f]-=1
            if k==0:
                while need[all_nums[i][1]]<0:
                    need[all_nums[i][1]]+=1
                    i+=1
                # print(need)
                if res[1]-res[0]>num-all_nums[i][0]:
                    res=(all_nums[i][0],num)
                k+=1
                need[all_nums[i][1]]+=1
                i+=1
        return [] if res[1]>all_nums[len(all_nums)-1][0] else [res[0],res[1]]
posted @ 2021-08-03 16:43  Hitechr  阅读(139)  评论(0编辑  收藏  举报