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
-1e5 <= nums[i][j] <= 1e5
nums[i] 按非递减顺序排列
解析
- 只看第一列数0 4 5,此时最小的区间[0,5] ,
- 怎么缩小区间 ? 是不是看一下 0 所在的列表的下一个数,如果0后为4,那么列表变成了4 4 5,更新列表长度。
- 能否选择4,5 后的数 ? 选择这两个只会让区间增大。因此,每次找最小的数,然后加入此列的后一个数,每次更新区间最大值,最小值由优先队列维护。
- 最大值-最小值为区间大小,最大值随着每次加入队列更新。
- 怎么找到当前列表的后一个数?可以将加入队列中的每个数加上下标。
- 同样做法的题
code
class Solution {
public:
//优先队列
vector<int> smallestRange(vector<vector<int>>& nums) {
//小根堆
priority_queue<vector<int>,vector<vector<int>>,
greater<vector<int>>> q;
int p_max=INT_MIN;
int m=nums.size();
int l=0,r=INT_MAX;
// 将首元素放入队列
for(int i=0;i<m;i++){
q.push({nums[i][0],i,0});
p_max=max(p_max,nums[i][0]);
}
while(!q.empty()){
auto tmp=q.top();
int val=tmp[0],x=tmp[1],y=tmp[2];
q.pop();
if(p_max-tmp[0]<r-l){
l=tmp[0];
r=p_max;
}
// 如果当前区间的最后一个值沦为了最小值,就停止了,
//说明最小值不会更改了,当然更新大的值,只会让右边界更大。
if(y+1>=nums[x].size())
break;
q.push({nums[x][y+1],x,y+1});
p_max=max(p_max,nums[x][y+1]);
}
return {l,r};
}
};