Leetcode 632. 最小区间 C++

Leetcode 632. 最小区间

题目

你有 k 个升序排列的整数数组。找到一个最小区间,使得 k 个列表中的每个列表至少有一个数包含在其中。

我们定义如果 b-a < d-c 或者在 b-a == d-c 时 a < c,则区间 [a,b] 比 [c,d] 小。

示例:

输入:[[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] 中。

注意:

  1. 给定的列表可能包含重复元素,所以在这里升序表示 >= 。
  2. 1 <= k <= 3500
  3. -105 <= 元素的值 <= 105
  4. 对于使用Java的用户,请注意传入类型已修改为List。重置代码模板后可以看到这项改动。

题解

滑动窗口,我们将每个数组列表的元素整合到一个数组中,我们的目标就是找到一个窗口,其内的元素包含所有的列表。然后比较左右边界。详细过程见代码

代码

bool sortVector(vector<int>& v1,vector<int>& v2){
    return v1[0]<v2[0];
}
class Solution {
public:
    vector<int> smallestRange(vector<vector<int>>& nums) {
        vector<vector<int>> num;
        int n = nums.size();
        for(int i=0; i<n; i++){
            for(int j=0; j<nums[i].size(); j++){
                num.push_back({nums[i][j],i});			//将每个列表的数字整合到一个新的数组中,需要记录它所属第几个列表
            }
        }
        sort(num.begin(),num.end(),sortVector);
        vector<int> time(n,0);
        int i=0,j=0,cnt=0;
        int res_l=0,res_r=INT_MAX;
        while(i<num.size()){		//滑动窗口
            while(j<num.size() && cnt != n){		//找到一个窗口,其内元素所属列表应包含所有的列表
                if(time[num[j][1]]==0)  cnt++;		//当前所属列表第一次出现
                time[num[j][1]]++;
                j++;
            }
            if(cnt != n)    break;
            if(res_r-res_l > num[j-1][0]-num[i][0]){		//比较是否区间比答案区间小
                res_l = num[i][0];
                res_r = num[j-1][0];
            }else if(res_r-res_l ==  num[j-1][0]-num[i][0] && res_l>num[i][0]){
                res_l = num[i][0];
                res_r = num[j-1][0];
            }
            time[num[i][1]]--;
            if(time[num[i][1]]==0)  cnt--;
            i++;
        }
        return {res_l,res_r};
    }
};

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/smallest-range-covering-elements-from-k-lists
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

你可能感兴趣的:(Leetcode 632. 最小区间 C++)