你有 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] 中。
注意:
滑动窗口,我们将每个数组列表的元素整合到一个数组中,我们的目标就是找到一个窗口,其内的元素包含所有的列表。然后比较左右边界。详细过程见代码
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
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。