632. Smallest Range


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. The 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>.
  5. And after you reset the code template, you’ll see this point.

方法1: priority_queue

官方题解:https://leetcode.com/problems/smallest-range/solution/

思路:

官方题解第三种方法将思路讲的很清楚。首先我们每个stream取一个点,确定了min 和 max,也有了range,接下来如何缩小range?max现在不能减小,所以选择增大min。找到min所在的stream,向前推进一个,再次比较找到新的min,和max。注意,这个找min和max的过程如果用pointer的方法,需要O(k),但是如果用priority queue,只需要o(logk)。对于min我们需要知道取到最小以后,如何向前推进,所以还要同时记录该数字来自哪条stream,以及它当前所处的index。在这里将{num , i} 组成pair存在pq里一起排序,而用一个k长度的vector记录每条steam行进到的index。其他的方法还可能使用iterator。对于max来讲,每一次我们并不会直接推进,而是被动的被下一次pop出来的数字不断向上拉,所以用一个int mx,来max(mx,newpopped)就可以。

易错点:

  1. 当任何一条stream结束之后,搜索可以结束。

Complexity

Time complexity: O(n log k)
Space complexity: O(k)

class Solution {
public:
    vector<int> smallestRange(vector<vector<int>>& nums) {
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
         int k = nums.size();
        vector<int> result(2, 0);
        vector<int> pt(k, 0);
        int mx = INT_MIN;
        int range = INT_MAX;
       
        
        for (int i = 0; i < k; i++) {
            //if (nums[i].empty()) return {};
            q.push({nums[i][0], i});
            mx = max(mx, nums[i][0]);
        }
    
        while (true) {
            int mn = q.top().first;
            int i = q.top().second;
            q.pop();
           
            if (mx - mn < range) {
                range = mx - mn;
                result[0] = mn;
                result[1] = mx;
            }
            
            if (pt[i] == nums[i].size() - 1) break;
            
            pt[i]++;
            mx = max(mx, nums[i][pt[i]]);
            q.push({nums[i][pt[i]], i});
        }
        return result;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值