LeetCode Add to List 632. Smallest Range

本文介绍了一种解决最小范围问题的有效算法,通过使用优先队列和动态更新策略,该算法能够在多项列表中找到覆盖所有列表的最小数值范围。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题:https://leetcode.com/problems/smallest-range/description/


You have k lists of sorted integers in ascending order. Find the smallest range that includes at least one number from each of the k lists.

We define the range [a,b] is smaller than range [c,d] if b-a < d-c or a < c if b-a == d-c.

Example 1:

Input:[[4,10,15,24,26], [0,9,12,20], [5,18,22,30]]
Output: [20,24]
Explanation:
List 1: [4, 10, 15, 24,26], 24 is in range [20,24].
List 2: [0, 9, 12, 20], 20 is in range [20,24].
List 3: [5, 18, 22, 30], 22 is in range [20,24].

Note:
1.he given list may contain duplicates, so ascending order means >= here.
2.1 <= k <= 3500
3.-105 <= value of elements <= 105.
4.For Java users, please note that the input type has been changed to List< List< Integer>>. And after you reset the code template, you’ll see this point.


next矩阵是一个链表,由每一行中的一个数组成。
next矩阵中每个元素的值代表其对应的列坐标。如next[2] == 3,那么next[2]就代表第三行第四列的数。
min_i对应的是当前next矩阵中坐标对应的值中最小值的行坐标。

举例: nums[2][3]是最小值,此时next[2]应该等于3
而这个时候的min_i的值等于2

1.建立一个next矩阵,矩阵长度为nums.size(),且全部初始化为0.
2.找到next矩阵中的最小最大值。
3.创建循环,每次都取出当前next中min_i对应的元素。将其和最大值组成的范围和之前的范围相比较。
4.如果新生成的范围比之前小,那么更新范围为当前最小最大值。
5.更新当前最小值对应next中的值。并将先前最大值和更新的next[min_i]对应的值比较,MAX = max(MAX, nums[min_i][next[min_i]]);
6.直到有一行被遍历完之前,重复2-5步。

为了减少每次查找next中元素对应的值的最小值的时间,利用priority_queue建立一个最小堆。堆中元素为pair< int,int>。由next[min_i]和nums[min_i][next[min_i]]组成
每次取出最顶上的数也就是当前next对应的数值中的最小值,再得到其对应的next中的位置,也就是min_i。然后将取出的pair从堆中删除。在经历上述的3,4,5步后,将更新后的 min_i对应的数对pair加到堆中。

循环完成后将得到的范围返回。


#include <iostream>
#include <vector>
#include<functional>
#include <limits>
#include<queue>
#include <algorithm>
using namespace std;
class Solution {
public:
    vector<int> smallestRange(vector<vector<int>>& nums) {
        int x = 0, y = INT_MAX, MAX = INT_MIN, min_i = 0;
        bool flag = 1;
        vector<int> next(nums.size());
        struct cmp {
            bool operator()(pair<int, int> p1, pair<int, int> p2) {
                return p1.second > p2.second;
            }
        };
        priority_queue<pair<int, int>, vector<pair<int, int>>, cmp >  p;
        for (int i = 0; i < nums.size(); i++) {
            next[i] = 0;
            p.push(make_pair(i, nums[i][0]));
            MAX = max(MAX, nums[i][0]);
        }
        while(flag) {
            int min_i = p.top().first;
            p.pop();
            if (y - x > MAX - nums[min_i][next[min_i]]) {
                x = nums[min_i][next[min_i]];
                y = MAX;
            }
            next[min_i]++;
            if (next[min_i] == nums[min_i].size()) {
                flag = false;
                break;
            }
            p.push(make_pair(min_i, nums[min_i][next[min_i]]));
            MAX = max(MAX, nums[min_i][next[min_i]]);
        }
        return vector<int>({x, y});
    }
};
int main() {
    Solution s;
    vector<vector<int> > v = { {4,10,15,24,26},{0,9,12,20},{5,18,22,30} };
    vector<int> z = s.smallestRange(v);
    cout << z[0]  << " " << z[1] << endl;
}

86 / 86 test cases passed.
Status: Accepted
Runtime: 39 ms

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值