LeetCode 632.最小区间

LeetCode 632.最小区间_第1张图片
传送门: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;
        
    }
};

你可能感兴趣的:(LeetCode,Heap,堆栈,数据结构,算法)