传送门:https://leetcode-cn.com/problems/smallest-range-covering-elements-from-k-lists/
这道题一上来就蒙圈了,感觉没什么套路,模板。
- 需要明确的是,答案必定是某个列表里的最小值,然后其他列表里都是取的第一个大于等于它的数。
- 那么我们需要在迭代中更新答案,初始区间肯定是由每个列表里的最小值组成 (因为我们需要在相同大小区间里取左端点最小的,所以从小的开始更新)。
- 那么,我们该如何更新呢?大概也就是去掉目前的最小值bi,而让第二个最小值成为当前最小值aj,而去掉的最小值换成那个列表中后一个元素(这个元素也是保证在这个列表里第一个大于等于当前最小值ai),并且更新最大值,然后更新答案区间。
- 于是,我们发现需要动态维护一个最小有序序列,可以用堆或者红黑树。
class Solution {
private:
struct node{
public:
int val, row, idx;
node(int x = 0, int y = 0, int z = 0)
:val{x}, row{y}, idx{z} { }
bool operator < (const node & rhs)const{
return val > rhs.val;
}
};
public:
vector<int> smallestRange(vector<vector<int>>& nums) {
priority_queue<node> min_heap;
int mx = INT_MIN, n = nums.size();
for (int i = 0; i < n; ++i){
const vector<int> & t = nums[i];
min_heap.push({t[0], i, 0});
mx = max(t[0], mx);
}
vector<int> ans = {min_heap.top().val, mx};
while (1){
const node & cur = min_heap.top();
int r = cur.row, i = cur.idx;
min_heap.pop();
if(i == nums[r].size() - 1) break;
min_heap.push({nums[r][i + 1], r, i + 1});
mx = max(mx, nums[r][i + 1]);
if(mx - min_heap.top().val < ans[1] - ans[0])
ans[1] = mx, ans[0] = min_heap.top().val;
}
return ans;
}
};